From a771c74e76a22099bbedee3ff32829c465429d90 Mon Sep 17 00:00:00 2001 From: Mike Crute Date: Tue, 28 Jul 2015 21:02:14 -0700 Subject: Initial import --- LICENSE.txt | 676 +++ Makefile.in | 513 ++ README.txt | 122 + bin/linux/libsndfile.a | Bin 0 -> 1458218 bytes bin/linux/libsndfile.so | Bin 0 -> 1008269 bytes bin/linux/libsndfile.so.1 | Bin 0 -> 1008269 bytes bin/linux/libsndfile.so.1.0.17 | Bin 0 -> 1008269 bytes bin/ppc_10.3/libsndfile.1.0.16.dylib | Bin 0 -> 1108848 bytes bin/ppc_10.3/libsndfile.1.dylib | Bin 0 -> 1108848 bytes bin/ppc_10.3/libsndfile.dylib | Bin 0 -> 1108848 bytes bin/ppc_10.4/libportaudio.a | Bin 0 -> 97728 bytes bin/ppc_10.4/libportaudio.dylib | Bin 0 -> 174848 bytes bin/ppc_10.4/libportaudio.dylib.0.0.18 | Bin 0 -> 105132 bytes bin/ppc_10.4/libsndfile.1.dylib.gz | Bin 0 -> 628026 bytes bin/win32/libsndfile-1.dll | Bin 0 -> 1235390 bytes configure | 120 + configure.in | 41 + doc/ADATFS.txt | 529 ++ doc/COMPILING.txt | 39 + doc/DEVELOPING.txt | 270 + doc/HARDWARE.txt | 34 + doc/LIVERECOVERY.txt | 25 + doc/MAILING.txt | 28 + doc/RELEASE.txt | 474 ++ doc/SYXformat.txt | 22 + doc/TESTPLAN.txt | 130 + doc/artwork/DMG_Background.png | Bin 0 -> 101824 bytes doc/artwork/DMG_Background.psd | Bin 0 -> 521073 bytes doc/artwork/HD24Connect.icns | Bin 0 -> 122133 bytes doc/artwork/HD24_vipower.jpg | Bin 0 -> 118233 bytes doc/artwork/Icon.psd | Bin 0 -> 263021 bytes doc/artwork/hd24connect.jpg | Bin 0 -> 17791 bytes doc/artwork/hd24display.png | Bin 0 -> 84562 bytes doc/artwork/hd24pc.jpg | Bin 0 -> 72433 bytes doc/hd24tools_manual.odt | Bin 0 -> 1243066 bytes doc/hd24tools_manual.pdf | Bin 0 -> 2167182 bytes images/longliverec.h24 | Bin 0 -> 986112 bytes images/unquickformat.h24 | Bin 0 -> 10752 bytes scripts/backupscript.txt | 5174 ++++++++++++++++++++ scripts/decodemtc | 127 + scripts/encode_smpte.pl | 181 + scripts/genbackupscript.pl | 98 + scripts/hd24arm1 | 2 + scripts/hd24arm1-16 | 2 + scripts/hd24arm1-24 | 2 + scripts/hd24arm2 | 2 + scripts/hd24getinfo | 2 + scripts/hd24idreq | 3 + scripts/hd24mute1 | 2 + scripts/hd24play | 3 + scripts/hd24stop | 3 + scripts/hd24unarmall | 2 + scripts/midi.c | 40 + scripts/mtcspeak | 34 + scripts/off2sec.pl | 19 + scripts/sec2off.pl | 17 + scripts/showstoppedmtc | 33 + scripts/sl2o.pl | 23 + src/frontend/WidgetPDial.fl | 131 + src/frontend/dialog_choosedevice.fl | 99 + src/frontend/dialog_filesize.fl | 131 + src/frontend/dialog_fromto.fl | 50 + src/frontend/dialog_newproject.fl | 86 + src/frontend/dialog_newsong.fl | 352 ++ src/frontend/dialog_options.fl | 131 + src/frontend/dialog_rate.fl | 58 + src/frontend/dialog_rename.fl | 89 + src/frontend/dialog_setlength.fl | 204 + src/frontend/dialog_setlocate.fl | 209 + src/frontend/hd24connect.cpp | 326 ++ src/frontend/hd24connect.ico | Bin 0 -> 4286 bytes src/frontend/images/7seg_0.gif | Bin 0 -> 1154 bytes src/frontend/images/7seg_1.gif | Bin 0 -> 610 bytes src/frontend/images/7seg_2.gif | Bin 0 -> 1090 bytes src/frontend/images/7seg_3.gif | Bin 0 -> 1102 bytes src/frontend/images/7seg_4.gif | Bin 0 -> 687 bytes src/frontend/images/7seg_5.gif | Bin 0 -> 694 bytes src/frontend/images/7seg_6.gif | Bin 0 -> 1120 bytes src/frontend/images/7seg_7.gif | Bin 0 -> 633 bytes src/frontend/images/7seg_8.gif | Bin 0 -> 1162 bytes src/frontend/images/7seg_9.gif | Bin 0 -> 1107 bytes src/frontend/images/HD24_matrix.gif | Bin 0 -> 4205 bytes src/frontend/images/HD24_matrix_100.gif | Bin 0 -> 175 bytes src/frontend/images/HD24_matrix_101.gif | Bin 0 -> 143 bytes src/frontend/images/HD24_matrix_102.gif | Bin 0 -> 163 bytes src/frontend/images/HD24_matrix_103.gif | Bin 0 -> 164 bytes src/frontend/images/HD24_matrix_104.gif | Bin 0 -> 170 bytes src/frontend/images/HD24_matrix_105.gif | Bin 0 -> 101 bytes src/frontend/images/HD24_matrix_106.gif | Bin 0 -> 127 bytes src/frontend/images/HD24_matrix_107.gif | Bin 0 -> 138 bytes src/frontend/images/HD24_matrix_108.gif | Bin 0 -> 128 bytes src/frontend/images/HD24_matrix_109.gif | Bin 0 -> 141 bytes src/frontend/images/HD24_matrix_110.gif | Bin 0 -> 136 bytes src/frontend/images/HD24_matrix_111.gif | Bin 0 -> 166 bytes src/frontend/images/HD24_matrix_112.gif | Bin 0 -> 163 bytes src/frontend/images/HD24_matrix_113.gif | Bin 0 -> 160 bytes src/frontend/images/HD24_matrix_114.gif | Bin 0 -> 157 bytes src/frontend/images/HD24_matrix_115.gif | Bin 0 -> 160 bytes src/frontend/images/HD24_matrix_116.gif | Bin 0 -> 138 bytes src/frontend/images/HD24_matrix_117.gif | Bin 0 -> 136 bytes src/frontend/images/HD24_matrix_118.gif | Bin 0 -> 125 bytes src/frontend/images/HD24_matrix_119.gif | Bin 0 -> 137 bytes src/frontend/images/HD24_matrix_120.gif | Bin 0 -> 128 bytes src/frontend/images/HD24_matrix_121.gif | Bin 0 -> 160 bytes src/frontend/images/HD24_matrix_122.gif | Bin 0 -> 163 bytes src/frontend/images/HD24_matrix_123.gif | Bin 0 -> 173 bytes src/frontend/images/HD24_matrix_124.gif | Bin 0 -> 173 bytes src/frontend/images/HD24_matrix_125.gif | Bin 0 -> 173 bytes src/frontend/images/HD24_matrix_126.gif | Bin 0 -> 173 bytes src/frontend/images/HD24_matrix_127.gif | Bin 0 -> 173 bytes src/frontend/images/HD24_matrix_32.gif | Bin 0 -> 129 bytes src/frontend/images/HD24_matrix_33.gif | Bin 0 -> 119 bytes src/frontend/images/HD24_matrix_34.gif | Bin 0 -> 106 bytes src/frontend/images/HD24_matrix_35.gif | Bin 0 -> 172 bytes src/frontend/images/HD24_matrix_36.gif | Bin 0 -> 172 bytes src/frontend/images/HD24_matrix_37.gif | Bin 0 -> 134 bytes src/frontend/images/HD24_matrix_38.gif | Bin 0 -> 140 bytes src/frontend/images/HD24_matrix_39.gif | Bin 0 -> 113 bytes src/frontend/images/HD24_matrix_40.gif | Bin 0 -> 104 bytes src/frontend/images/HD24_matrix_41.gif | Bin 0 -> 79 bytes src/frontend/images/HD24_matrix_42.gif | Bin 0 -> 125 bytes src/frontend/images/HD24_matrix_43.gif | Bin 0 -> 123 bytes src/frontend/images/HD24_matrix_44.gif | Bin 0 -> 113 bytes src/frontend/images/HD24_matrix_45.gif | Bin 0 -> 117 bytes src/frontend/images/HD24_matrix_46.gif | Bin 0 -> 140 bytes src/frontend/images/HD24_matrix_47.gif | Bin 0 -> 117 bytes src/frontend/images/HD24_matrix_48.gif | Bin 0 -> 154 bytes src/frontend/images/HD24_matrix_49.gif | Bin 0 -> 128 bytes src/frontend/images/HD24_matrix_50.gif | Bin 0 -> 172 bytes src/frontend/images/HD24_matrix_51.gif | Bin 0 -> 172 bytes src/frontend/images/HD24_matrix_52.gif | Bin 0 -> 170 bytes src/frontend/images/HD24_matrix_53.gif | Bin 0 -> 171 bytes src/frontend/images/HD24_matrix_54.gif | Bin 0 -> 168 bytes src/frontend/images/HD24_matrix_55.gif | Bin 0 -> 163 bytes src/frontend/images/HD24_matrix_56.gif | Bin 0 -> 175 bytes src/frontend/images/HD24_matrix_57.gif | Bin 0 -> 168 bytes src/frontend/images/HD24_matrix_58.gif | Bin 0 -> 124 bytes src/frontend/images/HD24_matrix_59.gif | Bin 0 -> 122 bytes src/frontend/images/HD24_matrix_60.gif | Bin 0 -> 126 bytes src/frontend/images/HD24_matrix_61.gif | Bin 0 -> 131 bytes src/frontend/images/HD24_matrix_62.gif | Bin 0 -> 124 bytes src/frontend/images/HD24_matrix_63.gif | Bin 0 -> 131 bytes src/frontend/images/HD24_matrix_64.gif | Bin 0 -> 173 bytes src/frontend/images/HD24_matrix_65.gif | Bin 0 -> 177 bytes src/frontend/images/HD24_matrix_66.gif | Bin 0 -> 177 bytes src/frontend/images/HD24_matrix_67.gif | Bin 0 -> 167 bytes src/frontend/images/HD24_matrix_68.gif | Bin 0 -> 175 bytes src/frontend/images/HD24_matrix_69.gif | Bin 0 -> 176 bytes src/frontend/images/HD24_matrix_70.gif | Bin 0 -> 169 bytes src/frontend/images/HD24_matrix_71.gif | Bin 0 -> 176 bytes src/frontend/images/HD24_matrix_72.gif | Bin 0 -> 171 bytes src/frontend/images/HD24_matrix_73.gif | Bin 0 -> 166 bytes src/frontend/images/HD24_matrix_74.gif | Bin 0 -> 163 bytes src/frontend/images/HD24_matrix_75.gif | Bin 0 -> 170 bytes src/frontend/images/HD24_matrix_76.gif | Bin 0 -> 162 bytes src/frontend/images/HD24_matrix_77.gif | Bin 0 -> 171 bytes src/frontend/images/HD24_matrix_78.gif | Bin 0 -> 172 bytes src/frontend/images/HD24_matrix_79.gif | Bin 0 -> 175 bytes src/frontend/images/HD24_matrix_80.gif | Bin 0 -> 170 bytes src/frontend/images/HD24_matrix_81.gif | Bin 0 -> 178 bytes src/frontend/images/HD24_matrix_82.gif | Bin 0 -> 177 bytes src/frontend/images/HD24_matrix_83.gif | Bin 0 -> 168 bytes src/frontend/images/HD24_matrix_84.gif | Bin 0 -> 159 bytes src/frontend/images/HD24_matrix_85.gif | Bin 0 -> 172 bytes src/frontend/images/HD24_matrix_86.gif | Bin 0 -> 164 bytes src/frontend/images/HD24_matrix_87.gif | Bin 0 -> 171 bytes src/frontend/images/HD24_matrix_88.gif | Bin 0 -> 169 bytes src/frontend/images/HD24_matrix_89.gif | Bin 0 -> 140 bytes src/frontend/images/HD24_matrix_90.gif | Bin 0 -> 169 bytes src/frontend/images/HD24_matrix_91.gif | Bin 0 -> 173 bytes src/frontend/images/HD24_matrix_92.gif | Bin 0 -> 173 bytes src/frontend/images/HD24_matrix_93.gif | Bin 0 -> 173 bytes src/frontend/images/HD24_matrix_94.gif | Bin 0 -> 173 bytes src/frontend/images/HD24_matrix_95.gif | Bin 0 -> 173 bytes src/frontend/images/HD24_matrix_96.gif | Bin 0 -> 173 bytes src/frontend/images/HD24_matrix_97.gif | Bin 0 -> 164 bytes src/frontend/images/HD24_matrix_98.gif | Bin 0 -> 173 bytes src/frontend/images/HD24_matrix_99.gif | Bin 0 -> 158 bytes src/frontend/images/HD24_matrix_arrowleft.gif | Bin 0 -> 152 bytes src/frontend/images/HD24_matrix_arrowright.gif | Bin 0 -> 149 bytes src/frontend/images/HD24_matrix_realsize.gif | Bin 0 -> 173 bytes src/frontend/images/HD24_matrix_writeenabled.gif | Bin 0 -> 176 bytes src/frontend/images/HD24_matrix_writeprotected.gif | Bin 0 -> 177 bytes src/frontend/images/aqua.bmp | Bin 0 -> 2559154 bytes src/frontend/images/aqua.rar | Bin 0 -> 44464 bytes src/frontend/images/aquabutton_down.gif | Bin 0 -> 1898 bytes src/frontend/images/aquabutton_up.gif | Bin 0 -> 1306 bytes src/frontend/images/button.gif | Bin 0 -> 3290 bytes src/frontend/images/button.xcf | Bin 0 -> 23360 bytes src/frontend/images/button_ffwd.gif | Bin 0 -> 2380 bytes src/frontend/images/button_ffwd_dn.gif | Bin 0 -> 2284 bytes src/frontend/images/button_lrc.gif | Bin 0 -> 1786 bytes src/frontend/images/button_lrc_dn.gif | Bin 0 -> 1708 bytes src/frontend/images/button_lrc_led.gif | Bin 0 -> 1807 bytes src/frontend/images/button_lrc_led_dn.gif | Bin 0 -> 1781 bytes src/frontend/images/button_lrc_led_on.gif | Bin 0 -> 1833 bytes src/frontend/images/button_lrc_led_on_dn.gif | Bin 0 -> 1765 bytes src/frontend/images/button_mute.gif | Bin 0 -> 1114 bytes src/frontend/images/button_mute_dn.gif | Bin 0 -> 1139 bytes src/frontend/images/button_play.gif | Bin 0 -> 2321 bytes src/frontend/images/button_play_dn.gif | Bin 0 -> 2231 bytes src/frontend/images/button_rec.gif | Bin 0 -> 2159 bytes src/frontend/images/button_rec_dn.gif | Bin 0 -> 2174 bytes src/frontend/images/button_rew.gif | Bin 0 -> 2331 bytes src/frontend/images/button_rew_dn.gif | Bin 0 -> 2214 bytes src/frontend/images/button_small.gif | Bin 0 -> 1145 bytes src/frontend/images/button_small_dn.gif | Bin 0 -> 1151 bytes src/frontend/images/button_solo.gif | Bin 0 -> 1089 bytes src/frontend/images/button_solo_dn.gif | Bin 0 -> 1139 bytes src/frontend/images/button_stop.gif | Bin 0 -> 2434 bytes src/frontend/images/button_stop_dn.gif | Bin 0 -> 2252 bytes src/frontend/images/button_stop_uplit.gif | Bin 0 -> 2321 bytes src/frontend/images/ch21.gif | Bin 0 -> 2870 bytes src/frontend/images/ch21.png | Bin 0 -> 92167 bytes src/frontend/images/down.gif | Bin 0 -> 344 bytes src/frontend/images/fader.gif | Bin 0 -> 1312 bytes src/frontend/images/ffwd.gif | Bin 0 -> 396 bytes src/frontend/images/hd24connect.png | Bin 0 -> 31182 bytes src/frontend/images/hd24connect.xpm | 38 + src/frontend/images/hd24connect_64x64.xpm | 355 ++ src/frontend/images/led1.gif | Bin 0 -> 524 bytes src/frontend/images/led10.gif | Bin 0 -> 323 bytes src/frontend/images/led2.gif | Bin 0 -> 523 bytes src/frontend/images/led3.gif | Bin 0 -> 523 bytes src/frontend/images/led4.gif | Bin 0 -> 522 bytes src/frontend/images/led5.gif | Bin 0 -> 525 bytes src/frontend/images/led6.gif | Bin 0 -> 524 bytes src/frontend/images/led7.gif | Bin 0 -> 525 bytes src/frontend/images/led8.gif | Bin 0 -> 531 bytes src/frontend/images/led9.gif | Bin 0 -> 526 bytes src/frontend/images/leds_3.gif | Bin 0 -> 1272 bytes src/frontend/images/leds_32.gif | Bin 0 -> 1272 bytes src/frontend/images/loop.gif | Bin 0 -> 619 bytes src/frontend/images/nextcue.gif | Bin 0 -> 591 bytes src/frontend/images/play.gif | Bin 0 -> 322 bytes src/frontend/images/prevcue.gif | Bin 0 -> 606 bytes src/frontend/images/rec.gif | Bin 0 -> 1035 bytes src/frontend/images/rew.gif | Bin 0 -> 400 bytes src/frontend/images/rewindtozero.gif | Bin 0 -> 685 bytes src/frontend/images/stop.gif | Bin 0 -> 363 bytes src/frontend/images/up.gif | Bin 0 -> 343 bytes src/frontend/images/wave.gif | Bin 0 -> 301 bytes src/frontend/images/xpbutton_dn.gif | Bin 0 -> 1336 bytes src/frontend/images/xpbutton_up.gif | Bin 0 -> 921 bytes src/frontend/images/xpbutton_uplit.gif | Bin 0 -> 921 bytes src/frontend/resource.rc | 2 + src/frontend/selftest.cpp | 646 +++ src/frontend/ui_hd24connect.fl | 4597 +++++++++++++++++ src/frontend/ui_hd24connect.txt | 387 ++ src/frontend/ui_hd24trackchannel.fl | 322 ++ src/frontend/ui_help_about.fl | 68 + src/frontend/ui_mixer.fl | 2225 +++++++++ src/frontend/ui_recorder.fl | 3639 ++++++++++++++ src/hd24hexview.cpp | 923 ++++ src/hd24info.cpp | 111 + src/hd24syx2bin.cpp | 113 + src/hd24towav.cpp | 233 + src/hd24wavefix.cpp | 207 + src/installer/PkgInfo.hd24connect | 2 + src/installer/PkgInfo.setup | 2 + src/installer/bin2c.c | 72 + src/installer/hd24connect_icon.png | Bin 0 -> 6895 bytes src/installer/icon.icns | Bin 0 -> 39662 bytes src/installer/info.plist.hd24connect | 23 + src/installer/info.plist.setup | 23 + src/installer/setup.cpp | 353 ++ src/installer/setupapi.cpp | 473 ++ src/installer/starthd24connect.command | 5 + src/installer/ui_askpasswd.fl | 78 + src/installer/ui_instdir.fl | 105 + src/installer/ui_license.fl | 80 + src/installer/ui_ready.fl | 49 + src/installer/ui_welcome.fl | 66 + src/installer/welcome.png | Bin 0 -> 81217 bytes src/lib/FL/FLTKstuff.H | 6 + src/lib/FL/Fl_Image_Button.H | 20 + src/lib/FL/Fl_Image_Button.cxx | 110 + src/lib/FL/Fl_Image_Repeat_Button.H | 20 + src/lib/FL/Fl_Image_Repeat_Button.cxx | 86 + src/lib/FL/Fl_Image_Toggle_Button.H | 20 + src/lib/FL/Fl_Image_Toggle_Button.cxx | 92 + src/lib/FL/Fl_Native_File_Chooser.H | 40 + src/lib/FL/Fl_Native_File_Chooser.cxx | 44 + src/lib/FL/Fl_Native_File_Chooser_FLTK.H | 89 + src/lib/FL/Fl_Native_File_Chooser_FLTK.cxx | 339 ++ src/lib/FL/Fl_Native_File_Chooser_MAC.H | 138 + src/lib/FL/Fl_Native_File_Chooser_MAC.cxx | 833 ++++ src/lib/FL/Fl_Native_File_Chooser_WIN32.H | 114 + src/lib/FL/Fl_Native_File_Chooser_WIN32.cxx | 765 +++ src/lib/FL/WidgetPDial.fl | 131 + src/lib/FL/common.cxx | 60 + src/lib/config.h | 11 + src/lib/convertlib.cpp | 311 ++ src/lib/convertlib.h | 39 + src/lib/hd24devicenamegenerator.cpp | 286 ++ src/lib/hd24devicenamegenerator.h | 52 + src/lib/hd24fs.cpp | 3002 ++++++++++++ src/lib/hd24fs.h | 432 ++ src/lib/hd24project.cpp | 477 ++ src/lib/hd24sndfile.cpp | 270 + src/lib/hd24sndfile.h | 37 + src/lib/hd24song.cpp | 2188 +++++++++ src/lib/hd24transferengine.cpp | 2143 ++++++++ src/lib/hd24transferengine.h | 188 + src/lib/hd24utils.cpp | 637 +++ src/lib/hd24utils.h | 64 + src/lib/memutils.cpp | 27 + src/lib/memutils.h | 15 + src/lib/nojack.cpp | 223 + src/lib/nojack.h | 467 ++ src/lib/portwin.h | 6 + src/lib/sharedlibs.cpp | 332 ++ src/lib/sharedlibs.h | 88 + src/lib/smpte.cpp | 221 + src/lib/smpte.h | 41 + src/lib/soundlibs.h | 15 + src/lib/xplat_dlfcn.h | 12 + src/test/co | 2 + src/test/portaudiotest.cpp | 158 + src/test/portaudiotest.h | 33 + src/test/portaudiotestold.cpp | 157 + windows/hd24connect.dsp | 338 ++ windows/hd24connect.dsw | 29 + windows/hd24hexview.dsp | 118 + windows/hd24info.dsp | 118 + windows/hd24tools.dsw | 65 + windows/hd24towav.dsp | 111 + 327 files changed, 41475 insertions(+) create mode 100644 LICENSE.txt create mode 100755 Makefile.in create mode 100644 README.txt create mode 100644 bin/linux/libsndfile.a create mode 100755 bin/linux/libsndfile.so create mode 100755 bin/linux/libsndfile.so.1 create mode 100755 bin/linux/libsndfile.so.1.0.17 create mode 100755 bin/ppc_10.3/libsndfile.1.0.16.dylib create mode 100755 bin/ppc_10.3/libsndfile.1.dylib create mode 100755 bin/ppc_10.3/libsndfile.dylib create mode 100644 bin/ppc_10.4/libportaudio.a create mode 100644 bin/ppc_10.4/libportaudio.dylib create mode 100644 bin/ppc_10.4/libportaudio.dylib.0.0.18 create mode 100755 bin/ppc_10.4/libsndfile.1.dylib.gz create mode 100755 bin/win32/libsndfile-1.dll create mode 100755 configure create mode 100644 configure.in create mode 100644 doc/ADATFS.txt create mode 100644 doc/COMPILING.txt create mode 100644 doc/DEVELOPING.txt create mode 100644 doc/HARDWARE.txt create mode 100644 doc/LIVERECOVERY.txt create mode 100644 doc/MAILING.txt create mode 100644 doc/RELEASE.txt create mode 100644 doc/SYXformat.txt create mode 100644 doc/TESTPLAN.txt create mode 100644 doc/artwork/DMG_Background.png create mode 100644 doc/artwork/DMG_Background.psd create mode 100644 doc/artwork/HD24Connect.icns create mode 100644 doc/artwork/HD24_vipower.jpg create mode 100644 doc/artwork/Icon.psd create mode 100644 doc/artwork/hd24connect.jpg create mode 100644 doc/artwork/hd24display.png create mode 100644 doc/artwork/hd24pc.jpg create mode 100644 doc/hd24tools_manual.odt create mode 100644 doc/hd24tools_manual.pdf create mode 100644 images/longliverec.h24 create mode 100644 images/unquickformat.h24 create mode 100644 scripts/backupscript.txt create mode 100755 scripts/decodemtc create mode 100755 scripts/encode_smpte.pl create mode 100755 scripts/genbackupscript.pl create mode 100755 scripts/hd24arm1 create mode 100755 scripts/hd24arm1-16 create mode 100755 scripts/hd24arm1-24 create mode 100755 scripts/hd24arm2 create mode 100755 scripts/hd24getinfo create mode 100755 scripts/hd24idreq create mode 100755 scripts/hd24mute1 create mode 100755 scripts/hd24play create mode 100755 scripts/hd24stop create mode 100755 scripts/hd24unarmall create mode 100644 scripts/midi.c create mode 100755 scripts/mtcspeak create mode 100755 scripts/off2sec.pl create mode 100755 scripts/sec2off.pl create mode 100755 scripts/showstoppedmtc create mode 100755 scripts/sl2o.pl create mode 100644 src/frontend/WidgetPDial.fl create mode 100755 src/frontend/dialog_choosedevice.fl create mode 100755 src/frontend/dialog_filesize.fl create mode 100755 src/frontend/dialog_fromto.fl create mode 100755 src/frontend/dialog_newproject.fl create mode 100755 src/frontend/dialog_newsong.fl create mode 100755 src/frontend/dialog_options.fl create mode 100755 src/frontend/dialog_rate.fl create mode 100755 src/frontend/dialog_rename.fl create mode 100755 src/frontend/dialog_setlength.fl create mode 100755 src/frontend/dialog_setlocate.fl create mode 100755 src/frontend/hd24connect.cpp create mode 100644 src/frontend/hd24connect.ico create mode 100644 src/frontend/images/7seg_0.gif create mode 100644 src/frontend/images/7seg_1.gif create mode 100644 src/frontend/images/7seg_2.gif create mode 100644 src/frontend/images/7seg_3.gif create mode 100644 src/frontend/images/7seg_4.gif create mode 100644 src/frontend/images/7seg_5.gif create mode 100644 src/frontend/images/7seg_6.gif create mode 100644 src/frontend/images/7seg_7.gif create mode 100644 src/frontend/images/7seg_8.gif create mode 100644 src/frontend/images/7seg_9.gif create mode 100644 src/frontend/images/HD24_matrix.gif create mode 100644 src/frontend/images/HD24_matrix_100.gif create mode 100644 src/frontend/images/HD24_matrix_101.gif create mode 100644 src/frontend/images/HD24_matrix_102.gif create mode 100644 src/frontend/images/HD24_matrix_103.gif create mode 100644 src/frontend/images/HD24_matrix_104.gif create mode 100644 src/frontend/images/HD24_matrix_105.gif create mode 100644 src/frontend/images/HD24_matrix_106.gif create mode 100644 src/frontend/images/HD24_matrix_107.gif create mode 100644 src/frontend/images/HD24_matrix_108.gif create mode 100644 src/frontend/images/HD24_matrix_109.gif create mode 100644 src/frontend/images/HD24_matrix_110.gif create mode 100644 src/frontend/images/HD24_matrix_111.gif create mode 100644 src/frontend/images/HD24_matrix_112.gif create mode 100644 src/frontend/images/HD24_matrix_113.gif create mode 100644 src/frontend/images/HD24_matrix_114.gif create mode 100644 src/frontend/images/HD24_matrix_115.gif create mode 100644 src/frontend/images/HD24_matrix_116.gif create mode 100644 src/frontend/images/HD24_matrix_117.gif create mode 100644 src/frontend/images/HD24_matrix_118.gif create mode 100644 src/frontend/images/HD24_matrix_119.gif create mode 100644 src/frontend/images/HD24_matrix_120.gif create mode 100644 src/frontend/images/HD24_matrix_121.gif create mode 100644 src/frontend/images/HD24_matrix_122.gif create mode 100644 src/frontend/images/HD24_matrix_123.gif create mode 100644 src/frontend/images/HD24_matrix_124.gif create mode 100644 src/frontend/images/HD24_matrix_125.gif create mode 100644 src/frontend/images/HD24_matrix_126.gif create mode 100644 src/frontend/images/HD24_matrix_127.gif create mode 100644 src/frontend/images/HD24_matrix_32.gif create mode 100644 src/frontend/images/HD24_matrix_33.gif create mode 100644 src/frontend/images/HD24_matrix_34.gif create mode 100644 src/frontend/images/HD24_matrix_35.gif create mode 100644 src/frontend/images/HD24_matrix_36.gif create mode 100644 src/frontend/images/HD24_matrix_37.gif create mode 100644 src/frontend/images/HD24_matrix_38.gif create mode 100644 src/frontend/images/HD24_matrix_39.gif create mode 100644 src/frontend/images/HD24_matrix_40.gif create mode 100644 src/frontend/images/HD24_matrix_41.gif create mode 100644 src/frontend/images/HD24_matrix_42.gif create mode 100644 src/frontend/images/HD24_matrix_43.gif create mode 100644 src/frontend/images/HD24_matrix_44.gif create mode 100644 src/frontend/images/HD24_matrix_45.gif create mode 100644 src/frontend/images/HD24_matrix_46.gif create mode 100644 src/frontend/images/HD24_matrix_47.gif create mode 100644 src/frontend/images/HD24_matrix_48.gif create mode 100644 src/frontend/images/HD24_matrix_49.gif create mode 100644 src/frontend/images/HD24_matrix_50.gif create mode 100644 src/frontend/images/HD24_matrix_51.gif create mode 100644 src/frontend/images/HD24_matrix_52.gif create mode 100644 src/frontend/images/HD24_matrix_53.gif create mode 100644 src/frontend/images/HD24_matrix_54.gif create mode 100644 src/frontend/images/HD24_matrix_55.gif create mode 100644 src/frontend/images/HD24_matrix_56.gif create mode 100644 src/frontend/images/HD24_matrix_57.gif create mode 100644 src/frontend/images/HD24_matrix_58.gif create mode 100644 src/frontend/images/HD24_matrix_59.gif create mode 100644 src/frontend/images/HD24_matrix_60.gif create mode 100644 src/frontend/images/HD24_matrix_61.gif create mode 100644 src/frontend/images/HD24_matrix_62.gif create mode 100644 src/frontend/images/HD24_matrix_63.gif create mode 100644 src/frontend/images/HD24_matrix_64.gif create mode 100644 src/frontend/images/HD24_matrix_65.gif create mode 100644 src/frontend/images/HD24_matrix_66.gif create mode 100644 src/frontend/images/HD24_matrix_67.gif create mode 100644 src/frontend/images/HD24_matrix_68.gif create mode 100644 src/frontend/images/HD24_matrix_69.gif create mode 100644 src/frontend/images/HD24_matrix_70.gif create mode 100644 src/frontend/images/HD24_matrix_71.gif create mode 100644 src/frontend/images/HD24_matrix_72.gif create mode 100644 src/frontend/images/HD24_matrix_73.gif create mode 100644 src/frontend/images/HD24_matrix_74.gif create mode 100644 src/frontend/images/HD24_matrix_75.gif create mode 100644 src/frontend/images/HD24_matrix_76.gif create mode 100644 src/frontend/images/HD24_matrix_77.gif create mode 100644 src/frontend/images/HD24_matrix_78.gif create mode 100644 src/frontend/images/HD24_matrix_79.gif create mode 100644 src/frontend/images/HD24_matrix_80.gif create mode 100644 src/frontend/images/HD24_matrix_81.gif create mode 100644 src/frontend/images/HD24_matrix_82.gif create mode 100644 src/frontend/images/HD24_matrix_83.gif create mode 100644 src/frontend/images/HD24_matrix_84.gif create mode 100644 src/frontend/images/HD24_matrix_85.gif create mode 100644 src/frontend/images/HD24_matrix_86.gif create mode 100644 src/frontend/images/HD24_matrix_87.gif create mode 100644 src/frontend/images/HD24_matrix_88.gif create mode 100644 src/frontend/images/HD24_matrix_89.gif create mode 100644 src/frontend/images/HD24_matrix_90.gif create mode 100644 src/frontend/images/HD24_matrix_91.gif create mode 100644 src/frontend/images/HD24_matrix_92.gif create mode 100644 src/frontend/images/HD24_matrix_93.gif create mode 100644 src/frontend/images/HD24_matrix_94.gif create mode 100644 src/frontend/images/HD24_matrix_95.gif create mode 100644 src/frontend/images/HD24_matrix_96.gif create mode 100644 src/frontend/images/HD24_matrix_97.gif create mode 100644 src/frontend/images/HD24_matrix_98.gif create mode 100644 src/frontend/images/HD24_matrix_99.gif create mode 100644 src/frontend/images/HD24_matrix_arrowleft.gif create mode 100644 src/frontend/images/HD24_matrix_arrowright.gif create mode 100644 src/frontend/images/HD24_matrix_realsize.gif create mode 100644 src/frontend/images/HD24_matrix_writeenabled.gif create mode 100644 src/frontend/images/HD24_matrix_writeprotected.gif create mode 100644 src/frontend/images/aqua.bmp create mode 100644 src/frontend/images/aqua.rar create mode 100644 src/frontend/images/aquabutton_down.gif create mode 100644 src/frontend/images/aquabutton_up.gif create mode 100644 src/frontend/images/button.gif create mode 100644 src/frontend/images/button.xcf create mode 100644 src/frontend/images/button_ffwd.gif create mode 100644 src/frontend/images/button_ffwd_dn.gif create mode 100644 src/frontend/images/button_lrc.gif create mode 100644 src/frontend/images/button_lrc_dn.gif create mode 100644 src/frontend/images/button_lrc_led.gif create mode 100644 src/frontend/images/button_lrc_led_dn.gif create mode 100644 src/frontend/images/button_lrc_led_on.gif create mode 100644 src/frontend/images/button_lrc_led_on_dn.gif create mode 100644 src/frontend/images/button_mute.gif create mode 100644 src/frontend/images/button_mute_dn.gif create mode 100644 src/frontend/images/button_play.gif create mode 100644 src/frontend/images/button_play_dn.gif create mode 100644 src/frontend/images/button_rec.gif create mode 100644 src/frontend/images/button_rec_dn.gif create mode 100644 src/frontend/images/button_rew.gif create mode 100644 src/frontend/images/button_rew_dn.gif create mode 100644 src/frontend/images/button_small.gif create mode 100644 src/frontend/images/button_small_dn.gif create mode 100644 src/frontend/images/button_solo.gif create mode 100644 src/frontend/images/button_solo_dn.gif create mode 100644 src/frontend/images/button_stop.gif create mode 100644 src/frontend/images/button_stop_dn.gif create mode 100644 src/frontend/images/button_stop_uplit.gif create mode 100644 src/frontend/images/ch21.gif create mode 100644 src/frontend/images/ch21.png create mode 100644 src/frontend/images/down.gif create mode 100644 src/frontend/images/fader.gif create mode 100755 src/frontend/images/ffwd.gif create mode 100755 src/frontend/images/hd24connect.png create mode 100644 src/frontend/images/hd24connect.xpm create mode 100644 src/frontend/images/hd24connect_64x64.xpm create mode 100644 src/frontend/images/led1.gif create mode 100644 src/frontend/images/led10.gif create mode 100644 src/frontend/images/led2.gif create mode 100644 src/frontend/images/led3.gif create mode 100644 src/frontend/images/led4.gif create mode 100644 src/frontend/images/led5.gif create mode 100644 src/frontend/images/led6.gif create mode 100644 src/frontend/images/led7.gif create mode 100644 src/frontend/images/led8.gif create mode 100644 src/frontend/images/led9.gif create mode 100644 src/frontend/images/leds_3.gif create mode 100644 src/frontend/images/leds_32.gif create mode 100755 src/frontend/images/loop.gif create mode 100755 src/frontend/images/nextcue.gif create mode 100755 src/frontend/images/play.gif create mode 100755 src/frontend/images/prevcue.gif create mode 100755 src/frontend/images/rec.gif create mode 100755 src/frontend/images/rew.gif create mode 100755 src/frontend/images/rewindtozero.gif create mode 100755 src/frontend/images/stop.gif create mode 100644 src/frontend/images/up.gif create mode 100755 src/frontend/images/wave.gif create mode 100644 src/frontend/images/xpbutton_dn.gif create mode 100644 src/frontend/images/xpbutton_up.gif create mode 100644 src/frontend/images/xpbutton_uplit.gif create mode 100644 src/frontend/resource.rc create mode 100644 src/frontend/selftest.cpp create mode 100755 src/frontend/ui_hd24connect.fl create mode 100644 src/frontend/ui_hd24connect.txt create mode 100644 src/frontend/ui_hd24trackchannel.fl create mode 100755 src/frontend/ui_help_about.fl create mode 100644 src/frontend/ui_mixer.fl create mode 100644 src/frontend/ui_recorder.fl create mode 100755 src/hd24hexview.cpp create mode 100755 src/hd24info.cpp create mode 100644 src/hd24syx2bin.cpp create mode 100755 src/hd24towav.cpp create mode 100755 src/hd24wavefix.cpp create mode 100644 src/installer/PkgInfo.hd24connect create mode 100644 src/installer/PkgInfo.setup create mode 100644 src/installer/bin2c.c create mode 100644 src/installer/hd24connect_icon.png create mode 100644 src/installer/icon.icns create mode 100644 src/installer/info.plist.hd24connect create mode 100644 src/installer/info.plist.setup create mode 100755 src/installer/setup.cpp create mode 100644 src/installer/setupapi.cpp create mode 100755 src/installer/starthd24connect.command create mode 100644 src/installer/ui_askpasswd.fl create mode 100644 src/installer/ui_instdir.fl create mode 100644 src/installer/ui_license.fl create mode 100644 src/installer/ui_ready.fl create mode 100644 src/installer/ui_welcome.fl create mode 100644 src/installer/welcome.png create mode 100644 src/lib/FL/FLTKstuff.H create mode 100644 src/lib/FL/Fl_Image_Button.H create mode 100644 src/lib/FL/Fl_Image_Button.cxx create mode 100644 src/lib/FL/Fl_Image_Repeat_Button.H create mode 100644 src/lib/FL/Fl_Image_Repeat_Button.cxx create mode 100644 src/lib/FL/Fl_Image_Toggle_Button.H create mode 100644 src/lib/FL/Fl_Image_Toggle_Button.cxx create mode 100644 src/lib/FL/Fl_Native_File_Chooser.H create mode 100644 src/lib/FL/Fl_Native_File_Chooser.cxx create mode 100644 src/lib/FL/Fl_Native_File_Chooser_FLTK.H create mode 100644 src/lib/FL/Fl_Native_File_Chooser_FLTK.cxx create mode 100644 src/lib/FL/Fl_Native_File_Chooser_MAC.H create mode 100644 src/lib/FL/Fl_Native_File_Chooser_MAC.cxx create mode 100644 src/lib/FL/Fl_Native_File_Chooser_WIN32.H create mode 100644 src/lib/FL/Fl_Native_File_Chooser_WIN32.cxx create mode 100644 src/lib/FL/WidgetPDial.fl create mode 100644 src/lib/FL/common.cxx create mode 100755 src/lib/config.h create mode 100755 src/lib/convertlib.cpp create mode 100755 src/lib/convertlib.h create mode 100644 src/lib/hd24devicenamegenerator.cpp create mode 100755 src/lib/hd24devicenamegenerator.h create mode 100755 src/lib/hd24fs.cpp create mode 100755 src/lib/hd24fs.h create mode 100755 src/lib/hd24project.cpp create mode 100644 src/lib/hd24sndfile.cpp create mode 100644 src/lib/hd24sndfile.h create mode 100755 src/lib/hd24song.cpp create mode 100644 src/lib/hd24transferengine.cpp create mode 100644 src/lib/hd24transferengine.h create mode 100755 src/lib/hd24utils.cpp create mode 100755 src/lib/hd24utils.h create mode 100644 src/lib/memutils.cpp create mode 100644 src/lib/memutils.h create mode 100755 src/lib/nojack.cpp create mode 100755 src/lib/nojack.h create mode 100644 src/lib/portwin.h create mode 100644 src/lib/sharedlibs.cpp create mode 100644 src/lib/sharedlibs.h create mode 100644 src/lib/smpte.cpp create mode 100644 src/lib/smpte.h create mode 100644 src/lib/soundlibs.h create mode 100644 src/lib/xplat_dlfcn.h create mode 100755 src/test/co create mode 100644 src/test/portaudiotest.cpp create mode 100644 src/test/portaudiotest.h create mode 100644 src/test/portaudiotestold.cpp create mode 100644 windows/hd24connect.dsp create mode 100644 windows/hd24connect.dsw create mode 100644 windows/hd24hexview.dsp create mode 100644 windows/hd24info.dsp create mode 100644 windows/hd24tools.dsw create mode 100644 windows/hd24towav.dsp diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..f15a692 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,676 @@ +HD24tools is released under the following license. + + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/Makefile.in b/Makefile.in new file mode 100755 index 0000000..85bcfde --- /dev/null +++ b/Makefile.in @@ -0,0 +1,513 @@ + +# =============================================== +# +# GENERIC CONFIG +# +# =============================================== +RELEASENUM=1.0.0alpha11 +INSTALLDIR=/usr/bin +INST_UI=src/installer/ +INST_BIN=bin/installer/ +BINDIR=bin/ +SRCDIR=src/ +UI=src/frontend/ +LIB=src/lib/ + +CCARGS=$(TMPCCARGS) -DLIBSND=Yes -DLIBJACK -DLIBPORTAUDIO + +# =============================================== +# +# ARCH DEPENDENT CONFIG +# +# =============================================== +ifeq ($(BUILD_ARCH), Win32) +PLATFORM=win32 +CC=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\" +INCLUDEDIRS=-I src/frontend -I src/lib -I src/backend -I /local/include -I /local/lib -I setup -I src -Bsrc -Bsrc/lib +LIBDIRS=-L/usr/local/lib -L/usr/X11R6/lib/ -L/local/lib/ -Lsrc/lib/ -Lsrc/ +UILIBS=-lstdc++ -lfltk -lm -lfltk_forms -lfltk_images -lgdi32 -lkernel32 -lole32 -luuid -lmsvcrt -luser32 -lwsock32 -lcomctl32 -lsupc++ `fltk-config --ldstaticflags` +CONSLIBS=-lstdc++ -lm -lkernel32 -lole32 -luuid -lmsvcrt -luser32 -lwsock32 -lcomctl32 -lsupc++ +PROGICON=$(BINDIR)icon.o +RESOURCE_LIBSNDFILE_1=$(BINDIR)win32/libsndfile-1.dll +RESOURCE_LIBSNDFILE_1_FILENAME=libsndfile-1.dll +RESOURCE_LIBSNDFILE_2= +RESOURCE_LIBSNDFILE_3= +CONSDEPS=-mwindows -mconsole +WINDEPS=$(BINDIR)nojack.o +WINEXT=.exe +endif + +ifeq ($(BUILD_ARCH), Darwin) +PLATFORM=OSX10.4 +CFLAGS=-no-cpp-precomp -arch ppc -arch i386 -isysroot /Developer/SDKs/MacOSX10.4u.sdk +CXXFLAGS=-no-cpp-precomp -arch ppc -arch i386 -isysroot /Developer/SDKs/MacOSX10.4u.sdk +CC=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/\" +LIBDIRS=-L/usr/local/lib -Lsrc/lib/ -L/sw/lib/ +INCLUDEDIRS=-I /usr/local/include -I /sw/include -I src/frontend -I src/lib -I src/backend -I setup +UILIBS=-framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework CoreServices `fltk-config --ldstaticflags` +CONSLIBS=-framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework CoreServices `fltk-config --ldstaticflags` +RESOURCE_LIBSNDFILE_1=$(BINDIR)ppc10.4/libsndfile.dylib +RESOURCE_LIBSNDFILE_1_FILENAME=libsndfile.1.dylib +endif + +ifeq ($(BUILD_ARCH), LinuxGNU) +PLATFORM=linux +CC=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/\" +LIBDIRS=-L/usr/local/lib -L/usr/X11R6/lib/ -L/local/lib/ -Lsrc/lib/ +INCLUDEDIRS=-I /usr/local/lib -I src/frontend -I src/lib -I src/backend -I /local/include -I setup +UILIBS=-lstdc++ -lgcc -lXpm `fltk-config --ldstaticflags` +CONSLIBS=-lstdc++ -lgcc +RESOURCE_LIBSNDFILE_1=$(BINDIR)linux/libsndfile.so +RESOURCE_LIBSNDFILE_1_FILENAME=libsndfile.so.1 +endif + +ifeq ($(BUILD_ARCH), Win32Linux) +PLATFORM=win32 +CC=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\" +INCLUDEDIRS=-I src/frontend -I src/lib -I src/backend -I /local/include -I /local/lib -I setup -I src -Bsrc -Bsrc/lib +LIBDIRS=-L/usr/local/lib -L/usr/X11R6/lib/ -L/local/lib/ -Lsrc/lib/ -Lsrc/ +UILIBS=-lstdc++ -lfltk -lm -lfltk_forms -lfltk_images -lgdi32 -lkernel32 -lole32 -luuid -lmsvcrt -luser32 -lwsock32 -lcomctl32 -lsupc++ `fltk-config --ldstaticflags` +CONSLIBS=-lstdc++ -lm -lkernel32 -lole32 -luuid -lmsvcrt -luser32 -lwsock32 -lcomctl32 -lsupc++ +WINDEPS=$(BINDIR)nojack.o +PROGICON=$(BINDIR)icon.o +RESOURCE_LIBSNDFILE_1=$(BINDIR)win32/libsndfile-1.dll +RESOURCE_LIBSNDFILE_1_FILENAME=libsndfile-1.dll +RESOURCE_LIBSNDFILE_2= +RESOURCE_LIBSNDFILE_3= +CONSDEPS=-mwindows -mconsole +WINEXT=.exe +endif + +# =============================================== +# +# DEFAULT TARGET +# +# =============================================== +all: hd24info hd24hexview hd24connect #hd24towav hd24wavefix + +# =============================================== +# +# CLEANUP TARGETS +# +# =============================================== +clean: + @rm -f $(BINDIR)*.o \ + $(BINDIR)*.cpp \ + $(BINDIR)*.cxx \ + $(UI)*.cxx \ + $(UI)*.h \ + hd24connect$(WINEXT) \ + hd24hexview$(WINEXT) \ + hd24towav$(WINEXT) \ + hd24wavefix$(WINEXT) \ + hd24info$(WINEXT) \ + src/lib/*~ \ + src/*~ \ + src/installer/*~ \ + src/installer/resource_*.c \ + src/installer/*.o \ + src/installer/ui_*.cxx \ + src/installer/ui_*.h \ + src/installer/bin2c \ + silent + +distclean: clean + @rm -f Makefile \ + makeincludes \ + setup/config.h \ + setup/Makefile.setup + +# =============================================== +# +# INSTALL TARGET +# +# =============================================== +install: hd24connect$(WINEXT) hd24hexview$(WINEXT) + cp hd24connect$(WINEXT) $(INSTALLDIR) + cp hd24info$(WINEXT) $(INSTALLDIR) + cp hd24hexview$(WINEXT) $(INSTALLDIR) + cp hd24towav$(WINEXT) $(INSTALLDIR) + cp hd24wavefix$(WINEXT) $(INSTALLDIR) + +# =============================================== +# +# INSTALL BUILDING +# +# =============================================== +installer: $(PLATFORM)_installer + echo Making installer for $(PLATFORM)... + +win32_installer: +linux_installer: hd24connect$(WINEXT) hd24hexview$(WINEXT) $(BINDIR)Fl_Native_File_Chooser.o + $(CC) $(CCARGS) $(SRCDIR)installer/bin2c.c -o $(SRCDIR)installer/bin2c$(WINEXT) + # create installer resources include file + echo // This file contains installer resources >$(SRCDIR)installer/installer_resources.h + $(SRCDIR)installer/bin2c$(WINEXT) images/longliverec.h24 $(SRCDIR)installer/resource_longliverec.c resource_longliverec + echo \#include \"resource_longliverec.c\" >>$(SRCDIR)installer/installer_resources.h + echo \#define resource_longliverec_filename \"longliverec.h24\" >>$(SRCDIR)installer/installer_resources.h + $(SRCDIR)installer/bin2c$(WINEXT) doc/hd24tools_manual.pdf $(SRCDIR)installer/resource_hd24tools_manual.c resource_hd24tools_manual + echo \#include \"resource_hd24tools_manual.c\" >>$(SRCDIR)installer/installer_resources.h + echo \#define resource_hd24tools_manual_filename \"hd24tools_manual.pdf\" >>$(SRCDIR)installer/installer_resources.h + $(SRCDIR)installer/bin2c$(WINEXT) images/unquickformat.h24 $(SRCDIR)installer/resource_unquickformat.c resource_unquickformat + echo \#include \"resource_unquickformat.c\" >>$(SRCDIR)installer/installer_resources.h + echo \#define resource_unquickformat_filename \"unquickformat.h24\" >>$(SRCDIR)installer/installer_resources.h + $(SRCDIR)installer/bin2c$(WINEXT) hd24connect$(WINEXT) $(SRCDIR)installer/resource_hd24connect.c resource_hd24connect + echo \#include \"resource_hd24connect.c\" >>$(SRCDIR)installer/installer_resources.h + echo \#define resource_hd24connect_filename \"hd24connect$(WINEXT)\" >>$(SRCDIR)installer/installer_resources.h + $(SRCDIR)installer/bin2c$(WINEXT) hd24hexview$(WINEXT) $(SRCDIR)installer/resource_hd24hexview.c resource_hd24hexview + echo \#include \"resource_hd24hexview.c\" >>$(SRCDIR)installer/installer_resources.h + echo \#define resource_hd24hexview_filename \"hd24hexview$(WINEXT)\" >>$(SRCDIR)installer/installer_resources.h + $(SRCDIR)installer/bin2c$(WINEXT) $(RESOURCE_LIBSNDFILE_1) $(SRCDIR)installer/resource_libsndfile_1.c resource_libsndfile_1 + echo \#include \"resource_libsndfile_1.c\" >>$(SRCDIR)installer/installer_resources.h + echo \#define resource_libsndfile_1_filename \"$(RESOURCE_LIBSNDFILE_1_FILENAME)\" >>$(SRCDIR)installer/installer_resources.h + echo \#define sharedlibdir \"\" >>$(SRCDIR)installer/installer_resources.h + echo // These are apple specific resources >>$(SRCDIR)installer/installer_resources.h + $(SRCDIR)installer/bin2c$(WINEXT) $(SRCDIR)installer/info.plist.hd24connect $(SRCDIR)installer/resource_plistconnect.c resource_plist_connect + echo \#include \"resource_plistconnect.c\" >>$(SRCDIR)installer/installer_resources.h + $(SRCDIR)installer/bin2c$(WINEXT) $(SRCDIR)installer/PkgInfo.hd24connect $(SRCDIR)installer/resource_pkginfoconnect.c resource_pkginfo_connect + echo \#include \"resource_pkginfoconnect.c\" >>$(SRCDIR)installer/installer_resources.h + fluid -c $(SRCDIR)installer/ui_welcome.fl; \ + cat ui_welcome.cxx|sed -e 's/\HD24VERSION/$(RELEASENUM)/' > $(SRCDIR)installer/ui_welcome.cxx; \ + mv ui_welcome.h $(SRCDIR)installer; \ + rm ui_welcome.cxx; \ + \ + fluid -c $(SRCDIR)installer/ui_license.fl; \ + cat ui_license.cxx|sed -e 's/\HD24VERSION/$(RELEASENUM)/' > $(SRCDIR)installer/ui_license.cxx; \ + mv ui_license.h $(SRCDIR)installer; \ + rm ui_license.cxx; \ + \ + fluid -c $(SRCDIR)installer/ui_instdir.fl; \ + cat ui_instdir.cxx|sed -e 's/\HD24VERSION/$(RELEASENUM)/' > $(SRCDIR)installer/ui_instdir.cxx; \ + mv ui_instdir.h $(SRCDIR)installer; \ + rm ui_instdir.cxx; \ + \ + fluid -c $(SRCDIR)installer/ui_ready.fl; \ + cat ui_ready.cxx|sed -e 's/\HD24VERSION/$(RELEASENUM)/' > $(SRCDIR)installer/ui_ready.cxx; \ + mv ui_ready.h $(SRCDIR)installer; \ + rm ui_ready.cxx; \ + \ + $(CC) $(CCARGS) -c $(SRCDIR)installer/ui_welcome.cxx -o $(SRCDIR)installer/ui_welcome.o $(INCLUDEDIRS) $(LIBDIRS);\ + $(CC) $(CCARGS) -c $(SRCDIR)installer/ui_license.cxx -o $(SRCDIR)installer/ui_license.o $(INCLUDEDIRS) $(LIBDIRS);\ + $(CC) $(CCARGS) -c $(SRCDIR)installer/ui_instdir.cxx -o $(SRCDIR)installer/ui_instdir.o $(INCLUDEDIRS) $(LIBDIRS);\ + $(CC) $(CCARGS) -c $(SRCDIR)installer/ui_ready.cxx -o $(SRCDIR)installer/ui_ready.o $(INCLUDEDIRS) $(LIBDIRS);\ + #@echo -e "\n\nInstaller spec files built. You must now make the appropriate target to get an installer file." + $(CREATEINSTALLERPACKAGE) + +createinstallerpackage_win32: + $(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) + fltk-config --post $(SRCDIR)installer/setup$(WINEXT) + echo Win32 setup post processing + mv src/installer/setup.exe . + zip a hd24tools_setup_$(RELEASENUM)_win32.zip setup.exe + mv setup.exe src/installer + +createinstallerpackage_linux: + $(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) + fltk-config --post $(SRCDIR)installer/setup + echo Linux setup post processing + mv setup setup.bck + mv src/installer/setup . + tar cvfz hd24tools_setup_$(RELEASENUM)_linuxi386.tgz setup + mv setup src/installer + mv setup.bck setup + +OSX10.4_installer: hd24connect$(WINEXT) hd24hexview$(WINEXT) $(BINDIR)Fl_Native_File_Chooser.o createinstallerpackage_mac +createinstallerpackage_mac: +# $(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) +# fltk-config --post $(SRCDIR)installer/setup$(WINEXT) + echo Mac setup post processing + rm -rf result + mkdir result + ditto hd24hexview result/ + mkdir result/HD24connect.app + mkdir result/HD24connect.app/Contents + cat $(SRCDIR)installer/info.plist.hd24connect|sed -e 's/HD24VERSION/$(RELEASENUM)/' > $(SRCDIR)installer/info.plist.hd24c; \ + ditto $(SRCDIR)installer/info.plist.hd24c result/HD24connect.app/Contents/info.plist + ditto $(SRCDIR)installer/PkgInfo.hd24connect result/HD24connect.app/Contents/ + mkdir result/HD24connect.app/Contents/MacOS + mkdir result/HD24connect.app/Contents/Resources + ditto $(SRCDIR)installer/icon.icns result/HD24connect.app/Contents/Resources + ditto hd24connect result/HD24connect.app/Contents/MacOS +# ditto doc/hd24tools_manual.pdf result + ditto images/longliverec.h24 result + ditto images/unquickformat.h24 result + cd bin/ppc_10.4/;gunzip libsnd*.gz; cd ../.. + ditto bin/ppc_10.4/*dylib* result/HD24connect.app/Contents/MacOS + cd bin/ppc_10.4/;gzip libsnd*; cd ../.. +# cp src/installer/starthd24connect.command result/ + rm -rf HD24tools.dmg + hdiutil create -fs HFS+ -srcfolder "result/" -volname "HD24tools" HD24tools.dmg + rm -rf hd24tools_$(RELEASENUM)-$(PLATFORM).dmg + hdiutil convert -format UDZO -o hd24tools_$(RELEASENUM)-$(PLATFORM).dmg HD24tools.dmg + + rm -rf HD24tools.dmg + rm -rf result + +#macrelease: +# rm -rf RELEASE +# rm -rf hd24_$(RELEASE_NUM)*.gz +# mkdir RELEASE +# mkdir RELEASE/usr +# mkdir RELEASE/usr/local +# mkdir RELEASE/usr/local/lib +# find HD24connect.app -print | cpio -pvcmdB RELEASE +# cp hd24connect RELEASE/HD24connect.app/Contents/MacOS +# cp hd24hexview RELEASE +# cp /usr/local/lib/libsndfile.1.0.16.dylib RELEASE/usr/local/lib +# cd RELEASE/usr/local/lib ; \ +# ln -s libsndfile.1.0.16.dylib libsndfile.1.dylib \ +# ln -s libsndfile.1.0.16.dylib libsndfile.dylib +# cd RELEASE ; \ +# find . -print | cpio -ovcB >../hd24_$(RELEASE_NUM)mac10.4.cpio +# gzip hd24_$(RELEASE_NUM)mac10.4.cpio +# cd RELEASE ; \ +# tar -cf ../hd24_$(RELEASE_NUM)mac10.4.tar . +# gzip hd24_$(RELEASE_NUM)mac10.4.tar + +# =============================================== +# +# CODE BUILDING +# +# =============================================== +hd24info: $(SRCDIR)hd24info.cpp $(BINDIR)hd24fs.o $(BINDIR)convertlib.o + $(CC) $(CCARGS) $(SRCDIR)hd24info.cpp $(BINDIR)memutils.o $(BINDIR)hd24fs.o $(BINDIR)hd24devicenamegenerator.o $(BINDIR)convertlib.o -o hd24info $(LIBDIRS) $(INCLUDEDIRS) $(CONSLIBS) $(CONSDEPS) + +hd24wavefix: $(SRCDIR)hd24wavefix.cpp $(BINDIR)convertlib.o + $(CC) $(CCARGS) $(SRCDIR)hd24wavefix.cpp $(BINDIR)memutils.o $(BINDIR)convertlib.o -lsndfile -o hd24wavefix $(LIBDIRS) $(INCLUDEDIRS) $(CONSLIBS) + +hd24towav: $(SRCDIR)hd24towav.cpp $(BINDIR)convertlib.o + $(CC) $(CCARGS) $(SRCDIR)hd24towav.cpp $(BINDIR)memutils.o $(BINDIR)convertlib.o -lsndfile -o hd24towav $(LIBDIRS) $(INCLUDEDIRS) $(CONSLIBS) + +hd24hexview: $(SRCDIR)hd24hexview.cpp $(BINDIR)hd24fs.o + $(CC) $(CCARGS) $(SRCDIR)hd24hexview.cpp $(BINDIR)memutils.o $(BINDIR)hd24fs.o $(BINDIR)hd24devicenamegenerator.o $(BINDIR)convertlib.o -o hd24hexview$(WINEXT) $(LIBDIRS) $(INCLUDEDIRS) $(CONSLIBS) $(CONSDEPS) + +$(BINDIR)Fl_Native_File_Chooser.o: $(LIB)FL/Fl_Native_File_Chooser.H $(LIB)FL/Fl_Native_File_Chooser.cxx + $(CC) $(CCARGS) -c $(LIB)FL/Fl_Native_File_Chooser.cxx -o $(BINDIR)Fl_Native_File_Chooser.o $(INCLUDEDIRS) $(LIBDIRS) + +$(BINDIR)Fl_Image_Button.o: $(LIB)FL/Fl_Image_Button.H $(LIB)FL/Fl_Image_Button.cxx + $(CC) $(CCARGS) -c $(LIB)FL/Fl_Image_Button.cxx -o $(BINDIR)Fl_Image_Button.o $(INCLUDEDIRS) $(LIBDIRS) + +$(BINDIR)Fl_Image_Repeat_Button.o: $(LIB)FL/Fl_Image_Repeat_Button.H $(LIB)FL/Fl_Image_Repeat_Button.cxx + $(CC) $(CCARGS) -c $(LIB)FL/Fl_Image_Repeat_Button.cxx -o $(BINDIR)Fl_Image_Repeat_Button.o $(INCLUDEDIRS) $(LIBDIRS) + +$(BINDIR)Fl_Image_Toggle_Button.o: $(LIB)FL/Fl_Image_Toggle_Button.H $(LIB)FL/Fl_Image_Toggle_Button.cxx + $(CC) $(CCARGS) -c $(LIB)FL/Fl_Image_Toggle_Button.cxx -o $(BINDIR)Fl_Image_Toggle_Button.o $(INCLUDEDIRS) $(LIBDIRS) + +hd24connect: $(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) + $(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 + +$(BINDIR)icon.o: $(UI)resource.rc + windres $(UI)resource.rc $(BINDIR)icon.o + +$(BINDIR)convertlib.o: $(LIB)convertlib.cpp $(LIB)convertlib.h + $(CC) $(CCARGS) -c $(LIB)convertlib.cpp -o $(BINDIR)convertlib.o $(INCLUDEDIRS) $(LIBDIRS) + +$(BINDIR)sharedlibs.o: $(LIB)sharedlibs.cpp $(LIB)sharedlibs.h + $(CC) $(CCARGS) -c $(LIB)sharedlibs.cpp -o $(BINDIR)sharedlibs.o $(INCLUDEDIRS) $(LIBDIRS) + +$(BINDIR)nojack.o: $(LIB)nojack.cpp $(LIB)nojack.h +$(BINDIR)nojack.o: $(LIB)nojack.cpp $(LIB)nojack.h + $(CC) $(CCARGS) -c $(LIB)nojack.cpp -o $(BINDIR)nojack.o $(INCLUDEDIRS) $(LIBDIRS) + +$(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 + cat $(UI)ui_hd24connect.cxx|sed -e 's/HD24VERSION/$(RELEASENUM)/' >$(BINDIR)ui_hd24connect.cxx +# $(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 + +$(BINDIR)ui_hd24connect.o: $(BINDIR)ui_hd24connect.cxx + $(CC) $(CCARGS) -c $(BINDIR)ui_hd24connect.cxx -o $(BINDIR)ui_hd24connect.o $(INCLUDEDIRS) $(LIBDIRS) + +$(BINDIR)hd24devicenamegenerator.o: $(LIB)hd24devicenamegenerator.h $(LIB)hd24devicenamegenerator.cpp $(BINDIR)convertlib.o + $(CC) $(CCARGS) -c $(LIB)hd24devicenamegenerator.cpp -o $(BINDIR)hd24devicenamegenerator.o $(INCLUDEDIRS) $(LIBDIRS) + +$(BINDIR)hd24utils.o: $(LIB)hd24utils.cpp $(LIB)hd24utils.h $(LIB)hd24project.cpp $(LIB)hd24song.cpp $(BINDIR)convertlib.o $(BINDIR)hd24devicenamegenerator.o + $(CC) $(CCARGS) -c $(LIB)hd24utils.cpp -o $(BINDIR)hd24utils.o $(INCLUDEDIRS) $(LIBDIRS) + +$(BINDIR)hd24sndfile.o: $(LIB)hd24sndfile.cpp $(LIB)hd24sndfile.h $(BINDIR)convertlib.o + $(CC) $(CCARGS) -c $(LIB)hd24sndfile.cpp -o $(BINDIR)hd24sndfile.o $(INCLUDEDIRS) $(LIBDIRS) + +$(BINDIR)hd24transferengine.o: $(LIB)hd24transferengine.cpp $(LIB)hd24transferengine.h $(LIB)hd24project.cpp $(LIB)hd24song.cpp $(BINDIR)convertlib.o $(BINDIR)ui_mixer.o + $(CC) $(CCARGS) -c $(LIB)hd24transferengine.cpp -o $(BINDIR)hd24transferengine.o $(INCLUDEDIRS) $(LIBDIRS) + +$(BINDIR)memutils.o: $(LIB)memutils.cpp $(LIB)memutils.h + $(CC) $(CCARGS) -c $(LIB)memutils.cpp -o $(BINDIR)memutils.o $(INCLUDEDIRS) $(LIBDIRS) + +$(BINDIR)smpte.o: $(LIB)smpte.cpp $(LIB)smpte.h + $(CC) $(CCARGS) -c $(LIB)smpte.cpp -o $(BINDIR)smpte.o $(INCLUDEDIRS) $(LIBDIRS) + +$(BINDIR)hd24fs.o: $(BINDIR)memutils.o $(LIB)hd24fs.cpp $(LIB)hd24fs.h $(LIB)hd24project.cpp $(LIB)hd24song.cpp $(BINDIR)convertlib.o $(BINDIR)hd24devicenamegenerator.o + $(CC) $(CCARGS) -c $(LIB)hd24fs.cpp -o $(BINDIR)hd24fs.o $(INCLUDEDIRS) $(LIBDIRS) + +$(BINDIR)ui_help_about.o: $(UI)ui_help_about.cxx + $(CC) $(CCARGS) -c $(UI)ui_help_about.cxx -o $(BINDIR)ui_help_about.o $(INCLUDEDIRS) $(LIBDIRS) + +$(BINDIR)ui_mixer.o: $(UI)ui_mixer.cxx + $(CC) $(CCARGS) -c $(UI)ui_mixer.cxx -o $(BINDIR)ui_mixer.o $(INCLUDEDIRS) $(LIBDIRS) + +$(BINDIR)ui_recorder.o: $(UI)ui_recorder.cxx + $(CC) $(CCARGS) -c $(UI)ui_recorder.cxx -o $(BINDIR)ui_recorder.o $(INCLUDEDIRS) $(LIBDIRS) + +$(BINDIR)ui_hd24trackchannel.o: $(UI)ui_hd24trackchannel.cxx + $(CC) $(CCARGS) -c $(UI)ui_hd24trackchannel.cxx -o $(BINDIR)ui_hd24trackchannel.o $(INCLUDEDIRS) $(LIBDIRS) + +$(BINDIR)dialog_fromhd24.o: $(UI)dialog_fromhd24.cxx $(UI)dialog_fromhd24.h + $(CC) $(CCARGS) -c $(UI)dialog_fromhd24.cxx -o $(BINDIR)dialog_fromhd24.o $(INCLUDEDIRS) $(LIBDIRS) + +$(BINDIR)dialog_rename.o: $(UI)dialog_rename.cxx + $(CC) $(CCARGS) -c $(UI)dialog_rename.cxx -o $(BINDIR)dialog_rename.o $(INCLUDEDIRS) $(LIBDIRS) + +$(BINDIR)dialog_options.o: $(UI)dialog_options.cxx + $(CC) $(CCARGS) -c $(UI)dialog_options.cxx -o $(BINDIR)dialog_options.o $(INCLUDEDIRS) $(LIBDIRS) + +$(BINDIR)dialog_choosedevice.o: $(UI)dialog_choosedevice.cxx + $(CC) $(CCARGS) -c $(UI)dialog_choosedevice.cxx -o $(BINDIR)dialog_choosedevice.o $(INCLUDEDIRS) $(LIBDIRS) + +$(BINDIR)dialog_setlength.o: $(UI)dialog_setlength.cxx + $(CC) $(CCARGS) -c $(UI)dialog_setlength.cxx -o $(BINDIR)dialog_setlength.o $(INCLUDEDIRS) $(LIBDIRS) + +$(BINDIR)dialog_filesize.o: $(UI)dialog_filesize.cxx + $(CC) $(CCARGS) -c $(UI)dialog_filesize.cxx -o $(BINDIR)dialog_filesize.o $(INCLUDEDIRS) $(LIBDIRS) + +$(BINDIR)dialog_newsong.o: $(UI)dialog_newsong.cxx + $(CC) $(CCARGS) -c $(UI)dialog_newsong.cxx -o $(BINDIR)dialog_newsong.o $(INCLUDEDIRS) $(LIBDIRS) + +$(UI)dialog_newsong.h: $(UI)dialog_newsong.fl + fluid -c $(UI)dialog_newsong.fl; \ + mv dialog_newsong.h $(UI); \ + mv dialog_newsong.cxx $(UI) + +$(UI)dialog_newsong.cxx: $(UI)dialog_newsong.fl + fluid -c $(UI)dialog_newsong.fl; \ + mv dialog_newsong.h $(UI); \ + mv dialog_newsong.cxx $(UI) + +$(BINDIR)dialog_newproject.o: $(UI)dialog_newproject.cxx + $(CC) $(CCARGS) -c $(UI)dialog_newproject.cxx -o $(BINDIR)dialog_newproject.o $(INCLUDEDIRS) $(LIBDIRS) + +$(UI)dialog_newproject.h: $(UI)dialog_newproject.fl + fluid -c $(UI)dialog_newproject.fl; \ + mv dialog_newproject.h $(UI); \ + mv dialog_newproject.cxx $(UI) + +$(UI)dialog_newproject.cxx: $(UI)dialog_newproject.fl + fluid -c $(UI)dialog_newproject.fl; \ + mv dialog_newproject.h $(UI); \ + mv dialog_newproject.cxx $(UI) + +$(BINDIR)dialog_setlocate.o: $(UI)dialog_setlocate.cxx + $(CC) $(CCARGS) -c $(UI)dialog_setlocate.cxx -o $(BINDIR)dialog_setlocate.o $(INCLUDEDIRS) $(LIBDIRS) + +$(BINDIR)dialog_fromto.o: $(UI)dialog_fromto.cxx + $(CC) $(CCARGS) -c $(UI)dialog_fromto.cxx -o $(BINDIR)dialog_fromto.o $(INCLUDEDIRS) $(LIBDIRS) + +$(BINDIR)hd24connect.o: $(UI)hd24connect.cpp $(UI)selftest.cpp $(BINDIR)ui_hd24connect.o $(BINDIR)hd24fs.o $(BINDIR)hd24utils.o + $(CC) $(CCARGS) -c $(UI)hd24connect.cpp -o $(BINDIR)hd24connect.o $(INCLUDEDIRS) $(LIBDIRS) + +$(UI)ui_hd24connect.h: $(UI)ui_hd24connect.fl $(UI)dialog_fromto.cxx $(UI)dialog_choosedevice.h + fluid -c $(UI)ui_hd24connect.fl; \ + cat ui_hd24connect.cxx|sed -e 's/\HD24VERSION/$(RELEASENUM)/' > $(UI)ui_hd24connect.cxx; \ + mv ui_hd24connect.h $(UI); \ + rm ui_hd24connect.cxx + +$(UI)ui_help_about.cxx: $(UI)ui_help_about.fl + fluid -c $(UI)ui_help_about.fl; \ + cat ui_help_about.cxx|sed -e 's/\HD24VERSION/$(RELEASENUM)/' > $(UI)ui_help_about.cxx; \ + mv ui_help_about.h $(UI); \ + rm ui_help_about.cxx + +$(UI)ui_recorder.cxx: $(UI)ui_recorder.fl $(UI)ui_hd24connect.h $(UI)ui_mixer.cxx + fluid -c $(UI)ui_recorder.fl; \ + cat ui_recorder.cxx|sed -e 's/\HD24VERSION/$(RELEASENUM)/' > $(UI)ui_recorder.cxx; \ + mv ui_recorder.h $(UI); \ + rm ui_recorder.cxx + +$(UI)ui_mixer.cxx: $(UI)ui_mixer.fl $(UI)ui_hd24connect.h + fluid -c $(UI)ui_mixer.fl; \ + cat ui_mixer.cxx|sed -e 's/\HD24VERSION/$(RELEASENUM)/' > $(UI)ui_mixer.cxx; \ + mv ui_mixer.h $(UI); \ + rm ui_mixer.cxx + +$(UI)ui_hd24trackchannel.h: $(UI)ui_hd24trackchannel.fl $(UI)ui_hd24connect.h + fluid -c $(UI)ui_hd24trackchannel.fl; \ + cat ui_hd24trackchannel.cxx|sed -e 's/\HD24VERSION/$(RELEASENUM)/' > $(UI)ui_hd24trackchannel.cxx; \ + mv ui_hd24trackchannel.h $(UI); \ + rm ui_hd24trackchannel.cxx + +$(UI)ui_hd24trackchannel.cxx: $(UI)ui_hd24trackchannel.fl $(UI)ui_hd24connect.h + fluid -c $(UI)ui_hd24trackchannel.fl; \ + cat ui_hd24trackchannel.cxx|sed -e 's/\HD24VERSION/$(RELEASENUM)/' > $(UI)ui_hd24trackchannel.cxx; \ + mv ui_hd24trackchannel.h $(UI); \ + rm ui_hd24trackchannel.cxx + +$(UI)dialog_filesize.h: $(UI)dialog_filesize.fl + fluid -c $(UI)dialog_filesize.fl; \ + mv dialog_filesize.h $(UI); \ + mv dialog_filesize.cxx $(UI) + +$(UI)dialog_filesize.cxx: $(UI)dialog_filesize.fl + fluid -c $(UI)dialog_filesize.fl; \ + mv dialog_filesize.h $(UI); \ + mv dialog_filesize.cxx $(UI) + +$(UI)dialog_setlength.cxx: $(UI)dialog_setlength.fl + fluid -c $(UI)dialog_setlength.fl; \ + mv dialog_setlength.h $(UI); \ + mv dialog_setlength.cxx $(UI) + +$(UI)dialog_setlocate.cxx: $(UI)dialog_setlocate.fl + fluid -c $(UI)dialog_setlocate.fl; \ + mv dialog_setlocate.h $(UI); \ + mv dialog_setlocate.cxx $(UI) + +$(UI)dialog_fromhd24.h: $(UI)dialog_fromhd24.fl + fluid -c $(UI)dialog_fromhd24.fl; \ + mv dialog_fromhd24.h $(UI); \ + mv dialog_fromhd24.cxx $(UI) + +$(UI)dialog_fromhd24.cxx: $(UI)dialog_fromhd24.fl + fluid -c $(UI)dialog_fromhd24.fl; \ + mv dialog_fromhd24.h $(UI); \ + mv dialog_fromhd24.cxx $(UI) + +$(UI)dialog_rename.cxx: $(UI)dialog_rename.fl + fluid -c $(UI)dialog_rename.fl; \ + mv dialog_rename.h $(UI); \ + mv dialog_rename.cxx $(UI) + +$(UI)dialog_options.cxx: $(UI)dialog_options.fl + fluid -c $(UI)dialog_options.fl; \ + mv dialog_options.h $(UI); \ + mv dialog_options.cxx $(UI) + +$(UI)dialog_fromto.cxx: $(UI)dialog_fromto.fl + fluid -c $(UI)dialog_fromto.fl; \ + mv dialog_fromto.h $(UI); \ + mv dialog_fromto.cxx $(UI) + +$(UI)ui_hd24connect.cxx: $(UI)ui_hd24connect.fl + fluid -c $(UI)ui_hd24connect.fl; \ + cat ui_hd24connect.cxx|sed -e 's/\HD24VERSION/$(RELEASENUM)/' > $(UI)ui_hd24connect.cxx; \ + mv ui_hd24connect.h $(UI); \ + rm ui_hd24connect.cxx + +$(UI)dialog_choosedevice.cxx: $(UI)dialog_choosedevice.fl + fluid -c $(UI)dialog_choosedevice.fl; \ + mv dialog_choosedevice.h $(UI); \ + mv dialog_choosedevice.cxx $(UI) + +$(UI)dialog_choosedevice.h: $(UI)dialog_choosedevice.fl + fluid -c $(UI)dialog_choosedevice.fl; \ + mv dialog_choosedevice.h $(UI); \ + mv dialog_choosedevice.cxx $(UI) + + +$(BINDIR)WidgetPDial.o: $(UI)WidgetPDial.cxx $(UI)WidgetPDial.h + $(CC) $(CCARGS) -c $(UI)WidgetPDial.cxx -o $(BINDIR)WidgetPDial.o $(INCLUDEDIRS) $(LIBDIRS) + +$(UI)WidgetPDial.h: $(UI)WidgetPDial.fl + fluid -c $(UI)WidgetPDial.fl; mv WidgetPDial.h $(UI); mv WidgetPDial.cc $(UI)WidgetPDial.cxx + +$(UI)WidgetPDial.cxx: $(UI)WidgetPDial.fl + fluid -c $(UI)WidgetPDial.fl; mv WidgetPDial.h $(UI); mv WidgetPDial.cc $(UI)WidgetPDial.cxx + +$(UI)WidgetPDial.fl: $(LIB)FL/WidgetPDial.fl + 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 @@ +What is the HD24tools suite? +============================ + +The HD24tools suite is a simple software suite that allows +Linux users to read disks of their Alesis HD24 ADAT recorders. +Developed in a cross-platform manner, it currently also compiles +for Windows and Mac, providing users with a free alternative to +Alesis' offering. + +Open source policy +================== + +The software was written as an independent effort. It contains +no code by Alesis, and is not supported by Alesis. + +In the development of this software, no Alesis-confidential +information was used. Instead, the necessary parts were +reverse-engineered, which is legal in the Netherlands. + +However, as a result, the correctness nor completeness of the +file system specifications can not be guaranteed. +Therefore, you are reminded that you use this software at your +own risk. + +AnalogFilter Class +================== +The author of ZynAddSubFX has granted me permission to use his +AnalogFilter class in HD24tools in closed-source form: + +"You may use the AnalogFilter class, but please acknowledge the +copyright of the AnalogFilter class (and tell that I give you a +specific permission to do so, to avoid confusion about GPL 2 +license)" + +This permission is no longer relevant because +1. I never ended up using this class; and +2. HD24tools is now open-source. + +General operation +================= +Most of the programs automatically detect and access the presence +of HD24 disks. + +If multiple HD24 disks are present, the first HD24 disk found will +be used by default. The tools search for HD24 disks in the following +order: + +/dev/hda,/dev/hdb,/dev/hdc,/dev/hdd +/dev/sda,/dev/sdb,/dev/sdc,/dev/sdd + +This should find most HD24 disks, regardless of the way that they +are connected to your PC (be it using a VIPowER drive bay, USB +connection or firewire interface). Should you be using another +device as disk, you can use the --dev=x option to point to +HD24 device with device path x. + +To be able to use the tools, the user running the programs must +have direct read access to the disk device. It is possible to +re-assign access rights of the disk device each time, but it +is probably more practical to update your group permissions and/or +add an entry to your /etc/fstab, for instance: + +/dev/hdc none auto devmode=0664 0 0 + +(I have not extensively tested this for optimal security). +You can ignore any boot time complaints about linux not being able +to mount the drive; it will try all the file system types it +knows but of course doesn't know how to work with HD24 drives. + +When using an internal drivebay, keep in mind that it may not +support hot-swapping. You probably need to switch off power to +exchange drives. In other words, if you fry your motherboard, +don't complain to me. + +The HD24 only accepts drives configured as master. As such, if +you use an internal drive bay, you probably end up with the HD24 +disk as /dev/hdc. + +The programs +============ +hd24hexview A debug-style hex viewer for (binary files and) hd24 disks. + + Without command line arguments, accesses the first + found hd24 disk in hex mode. + + Type ? in the program for help. + + Call the program with --dev=/dev/hdc to use + /dev/hdc as hd24 disk. If this disk is not + recognized as hd24 disk, use the --force option + to view the disk contents anyway. Use --expert + to enable write mode. + + All other programs that directly access the disk + support the --dev=x option but not the --force + option. + +hd24connect A program to download files from HD24 disks. + +hd24info A program that displays some info about the + hd24 disk. Mostly useful to detect the presence + or absence of hd24 disks. + (obsolete) + +hd24wavefix A program that attempts to fix corrupted audio that + sometimes occurs in long live recordings, usually when + recording to very high capacity drives. + +genbackupscript.pl + + A perl script to generate a script for hd24hexview + which will create a backup of the file system information + to the end of the drive. Now obsolete; this functionality + is now built-in into the HD24 library. + +syx2bin A program that attempts to decode the 7 bit HD24 .syx file + to a 8 bit binary file. + +hd24towav.cpp A program that converts raw hd24 data to wav files. + (obsolete) + + diff --git a/bin/linux/libsndfile.a b/bin/linux/libsndfile.a new file mode 100644 index 0000000..eccdf14 Binary files /dev/null and b/bin/linux/libsndfile.a differ diff --git a/bin/linux/libsndfile.so b/bin/linux/libsndfile.so new file mode 100755 index 0000000..002351f Binary files /dev/null and b/bin/linux/libsndfile.so differ diff --git a/bin/linux/libsndfile.so.1 b/bin/linux/libsndfile.so.1 new file mode 100755 index 0000000..002351f Binary files /dev/null and b/bin/linux/libsndfile.so.1 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 Binary files /dev/null and b/bin/linux/libsndfile.so.1.0.17 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 Binary files /dev/null and b/bin/ppc_10.3/libsndfile.1.0.16.dylib 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 Binary files /dev/null and b/bin/ppc_10.3/libsndfile.1.dylib differ diff --git a/bin/ppc_10.3/libsndfile.dylib b/bin/ppc_10.3/libsndfile.dylib new file mode 100755 index 0000000..656c8a6 Binary files /dev/null and b/bin/ppc_10.3/libsndfile.dylib differ diff --git a/bin/ppc_10.4/libportaudio.a b/bin/ppc_10.4/libportaudio.a new file mode 100644 index 0000000..fad24ca Binary files /dev/null and b/bin/ppc_10.4/libportaudio.a differ diff --git a/bin/ppc_10.4/libportaudio.dylib b/bin/ppc_10.4/libportaudio.dylib new file mode 100644 index 0000000..7124677 Binary files /dev/null and b/bin/ppc_10.4/libportaudio.dylib 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 Binary files /dev/null and b/bin/ppc_10.4/libportaudio.dylib.0.0.18 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 Binary files /dev/null and b/bin/ppc_10.4/libsndfile.1.dylib.gz differ diff --git a/bin/win32/libsndfile-1.dll b/bin/win32/libsndfile-1.dll new file mode 100755 index 0000000..31cfd6c Binary files /dev/null and b/bin/win32/libsndfile-1.dll differ diff --git a/configure b/configure new file mode 100755 index 0000000..836c6e0 --- /dev/null +++ b/configure @@ -0,0 +1,120 @@ +#!/bin/bash + +####################################################################### +# OS Setup Routines +####################################################################### +setup_win32() +{ + echo "Build environment... Microsoft Windows"; + BUILD_FOR='Win32' + PORTAUDIO_MAKEOPTS='-lwinmm' + MORELIBS="$MORELIBS -lwinmm -mwindows" +# MOREDEPS="$MOREDEPS \$(BINDIR)nojack.o" +} + + +setup_linux_gnu() +{ + echo "Build environment... GNU/Linux"; + BUILD_FOR='LinuxGNU' + PORTAUDIO_MAKEOPTS='-pthread' +} + + +setup_linux_win32() +{ + echo "Build environment... Microsoft Windows (Linux)" + BUILD_FOR='Win32Linux' + PORTAUDIO_MAKEOPTS='-lwinmm' + GCC='i586-mingw32msvc-gcc' +} + + +setup_darwin() +{ + echo "Build environment... Macintosh OS X"; + BUILD_FOR='Darwin' + JACK_MAKEOPTS='-L/sw/lib -I/sw/include' + PORTAUDIO_MAKEOPTS='-L/sw/lib -I/sw/include' + export CFLAGS="-no-cpp-precomp -arch ppc -arch i386 -isysroot /Developer/SDKs/MacOSX10.4u.sdk" + export CXXFLAGS="-no-cpp-precomp -arch ppc -arch i386 -isysroot /Developer/SDKs/MacOSX10.4u.sdk" +} + + +####################################################################### +# Library Tests +####################################################################### +find_fltk() +{ + TEST=`fltk-config --version | awk \ + 'BEGIN {FS="=";version="Unavailable"} 1==1 {version=$1} END {print version}'` + + if [ $? == 0 ]; then + echo "Searching for FLTK... found $TEST" + TMPCCARGS="$TMPCCARGS -DLIBFLTK=\"$TEST\"" + else + echo "Searching for FLTK... not found" + echo "Can't continue." + exit 1 + fi +} + + +####################################################################### +# Main Configure Routine +####################################################################### +main() +{ + [[ -e Makefile ]] && make clean + + MORELIBS='' # Extra libraries + MOREDEPS='' # Extra dependencies + BUILD_FOR='' # Build architecture + GCC='gcc' # GCC Command (different if building Win32 on Linux) + TMPCCARGS='' # Extra CC Arguments + + # Check for Windows + if [[ $BUILD_FOR == '' && \ + ($WINDIR == "C:\\WINNT" || $WINDIR == "C:\\WINDOWS") ]]; + then + setup_win32 + fi + + # Check for Linux or Win32 building on Linux + if [[ $BUILD_FOR == '' && \ + `if [ -e /proc/version ]; then cat /proc/version | grep Linux; fi` != "" ]] + then + if [ "$1" = "--os=win32" ]; then + setup_linux_win32 + else + setup_linux_gnu + fi + fi + + # Check for Mac OS X + if [[ $BUILD_FOR == '' && \ + ("`echo $version|grep powerpc-apple-darwin`" != "" || \ + "`echo $OSTYPE|grep darwin`" != "") ]] + then + setup_darwin $1 + fi + + # Check for Essential Libraries + find_fltk + + # Create the Makefile + echo "BUILD_ARCH=$BUILD_FOR" > Makefile + echo "MORELIBS=$MORELIBS" >> Makefile + echo "MOREDEPS=$MOREDEPS" >> Makefile + echo "TMPCCARGS=$TMPCCARGS" >> Makefile + + if [[ $1 == '--with-universal' ]]; then + echo "UNIVERSAL=true" >> Makefile + fi + + cat Makefile.in >> Makefile + + echo -e "\nConfiguration complete. If all looked OK, now run make."; +} + +main $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 @@ +# +# This is the start of an autotools build system. It's still very much a work +# in-progress and can't be reliably used yet. ~mcrute +# +m4_define(HD24TOOLS_VERSION, 1.0) + +AC_PREREQ(2.61) +AC_INIT(hd24tools, HD24TOOLS_VERSION, http://hd24tools.com/) + +# Checks for programs. +AC_PROG_CXX +AC_PROG_CC + +# Checks for libraries. +AC_SEARCH_LIBS([XpmCreatePixmapFromData], [Xpm]) +AC_SEARCH_LIBS([sf_command], [sndfile]) +AC_SEARCH_LIBS([jack_client_new], [jack]) +AC_SEARCH_LIBS([Pa_Initialize], [portaudio]) + +AC_HEADER_DIRENT +AC_HEADER_STDC +AC_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]) + +AC_HEADER_STDBOOL +AC_C_CONST +AC_TYPE_SIZE_T +AC_TYPE_SSIZE_T +AC_STRUCT_TM + +AC_FUNC_CLOSEDIR_VOID +AC_FUNC_MALLOC +AC_FUNC_MEMCMP +AC_FUNC_STAT +AC_FUNC_STRFTIME +AC_FUNC_STRTOD +AC_CHECK_FUNCS([floor getcwd memchr memset mkdir strchr strdup strtol]) +AC_CONFIG_FILES([Makefile]) + +AC_OUTPUT + +# 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 @@ +HD24 ADAT file system format + +Reading ADAT HD24 disks +----------------------- +In the ADAT FST file system, the part of the file system +that contains directory and song info is grouped in +32-bit words. When read on a regular PC, each group of +4 bytes will appear reversed. As such, when +a sector contains a string 'TADATSF ', we should read this +as 'ADAT FST'. In this document, we will assume that +doing the byte swapping needed to properly read the sectors +has already been done. + +It should be noted that the actual audio data has not +undergone such byte swapping. As such, WAV data +retrieved from the HD24 by FTP is stored in the same +byte order as the data on disk. + +The sector size used on HD24 disks is 512 bytes. +ADAT FST boasts disk support for disks up to 2 Terabyte. +This is achieved by using 32-bit pointers that point to +sector numbers. We will refer to these pointers as +sectorpointers. + +Writing ADAT HD24 disks +----------------------- +Writing HD24 disks is slightly tricky, because FST +filesystems contain backup copies of file system +sectors to help guarantee data consistency. +As a result, when we make an alteration to only the +first copy of the file system structure on disk, the +disk is considered inconsistent and the backup copy will +be written back by the HD24 recorder at the next use. + +The backup data is stored at the end of the disk, +in block-reverse order. +The original order is something like this: + +block 0 + sector 0 +block 1 + sector 1 +block 2 + sectors 2,3,4 +block 3 + sectors 5,6,7,8,9,10,11,12,13,14,15,16,17,18,19 +block 4-102 + 1 sector of project info +block 103- + song info block (2 sectors) + song allocation info block (5 sectors) + +The backup blocks are stored in reverse order, +however each backup block maintains the original +sector ordering. That is, + +block 0 has a backup at sector (end-0) + (where end=the last sector on disk) + +block 1 has a backup at sector (end-1) + +block 2, sectors 2,3,4 are backed up at sectors + end-4, end-3, end-2, respectively; + +block 3, sectors 5,6,7,8,9,10,11,12,13,14,15,16,17,18,19 + are backed up at sectors + end-19,end-18,end-17,end-16,end-15,...end-5, + respectively. + +The validity of a block is indicated by a checksum which +is stored in the last 4 bytes of a block (bytes 0x1FC, +0x1FD, 0x1FE, 0x1FF of the last sector of a block). + +The value of the checksum is such that sum of all 32-bit +words in the block (which may span several sectors) is 0. +When writing a block, we must make sure that the resulting +checksum of the block adds up to 0 again. + +A second check refers to bytes 0x1f8-0x1fb of the last +sector of a block. Bytes 0x1F8 and 0x1F9 contain the +least significant 16 bit of the sector number at which +the block starts. Thus, a project block which contains +1 sector and starts on sector 0x14 will contain the +values 0x14, 0x00 on bytes 0x1f8 and 0x1f9; a song entry +2 sectors long, and ending on sector 0x78 will contain +the byte values 0x77, 0x00 on offset 0x1f8 and 0x1f9, +respectively (because the song entry starts on sector +0x77). Bytes 0x1FA and 0x1FB of the last sector of the +block contain the bit-inverted value of 0x1F8 and 0x1F9**. + +** This paragraph assumes the sector is not byte-swapped +as described in the first paragraph of the document. + +When a block is not equal to its backup, the checksum +of both is validated. If one is valid and the other is +not, the valid copy is written over the invalid copy. + +General ADAT FST layout +----------------------- +The general ADAT FST layout is as follows: + +----------------------------------------------------------- +Sector 0 / Offset 0000:0000h +Superblock, identifies drive as an ADAT FST drive. +Size=512 bytes/0200h +----------------------------------------------------------- +Sector 1 / Offset 0000:0200h +Drive info +Size=512 bytes/0200h +----------------------------------------------------------- +Offset 0000:0400h +3 sectors, Song Entry Usage Table +Size=600h +----------------------------------------------------------- +Offset 0800h +15 sectors, Drive Usage Table +size=1e00h +----------------------------------------------------------- + / Offset 0000:2800h +Project info, 1 sector (512 bytes) per project entry +Size: 99*200h=c600h +----------------------------------------------------------- + / Offset 0000:ee00h +Song info, 7 sectors (3584 bytes) per song entry +----------------------------------------------------------- + Undo info +----------------------------------------------------------- + Audio data +----------------------------------------------------------- + File system backup +----------------------------------------------------------- + + +Superblock layout +----------------- +Offset 0-0fh Header line: + Offset 0 'ADAT FST' + Offset 8 Version number, e.g. '110 ' + Offset 12 signature bytes: 55h, aah, cch, 33h +Offset 10h-13h Size of audio block (0x480) +Offset 14h-17h Number of audio blocks per allocation cluster +Offset 18h-1fh 0 ? +Offset 20h-23h 0 ? +Offset 24h-27h 0 ? +Offset 28h-2bh 1 ? sectors in superblock? +Offset 2ch-2fh 1 ? sectors in drive info block + +Offset 30h-33h 2 ? sectornum of song entry usage table? +Offset 34h-37h 3 ? sectors in song entry usage table? + +Offset 38h-3bh 5 ? sectornum containing allocation info? +Offset 3ch-3fh 15/0fh - Number of sectors in allocation table? + +Offset 40h-43h 042fh=1071 ?? (anything to do with undo buffer?) + -- + On 1.2gb drive this formats as 0x20 00 00 00 + -- +Offset 44h-47h Number of free audio clusters on disk +Offset 48h-4bh SectorPointer to project info +Offset 4ch-4fh 1 +Offset 50h-53h Max allowed no. of projects? +Offset 54h-57h Max allowed no. of songs per project? +Offset 58h-5bh SectorPointer to first song info entry + +Offset 5ch-5fh 2 (sectors of song info entry w/o alloc info?) +Offset 60h-63h 5 (sectors of alloc info per song entry?) +Offset 64h-67h 7 (number of sectors that song info entries are apart?) +Offset 68h-6bh current number of songs on disk +Offset 78h-7bh 041fh (number of audio blocks reserved for undo buffer). + 1055 audio blocks=72 track minutes at 48 khz + Multiply by contents of offset 14h-17h for number of sectors + in undo buffer. + +Offset 7ch-7fh Sector pointer to audio data block on disk (0x1397f6). +Offset 80h-83h 32-bit word + number almost as big as number of sectors on disk + + This number is related to that on offset 0084h and + always seems to have a difference of 0x14a46B to + the end of the disk. + + 0084h 0080h + 40 gb disk: + 0x04c92d7f - 0x04B48914 = 0x14A46B + 120gb disk: + 0x0df94baf - 0x0de4a744 = 0x14A46B + + Perhaps the value is the number of allocatable sectors + on disk? + (1397f6 used in the beginning; an undo buffer is not + needed at the end of the drive) + + 0x10C75 used for actual filesystem.? + 0x1397f6 (first data sector on drive) - (0x41f(size of undo buffer in audio blocks) * 0x480(size of audio block in sectors)) = 0x10C76 + first data sector is not part of FS so this makes sense. + +offset 84h-87h 32-bit word, highest sector number on disk. + A backup of the first sector can be found here. +offset 88h-1F7 (empty, zero - reserved for future use?) +offset 1f8-1FF Checksum information. + +Drive info layout +----------------- +Sector 1 +Offset 0 8 byte drive name (for compatibility with + older ADAT FST versions), should be considered + obsolete. Replaced by name at offset 01bh. +Offset 8-9 null bytes +Offset 0ah-0bh 2 more bytes for drive name. Should be considered + obsolete +Offset 10h SectorPointer to last active project. +offset 20h List of 32-bit sector pointers to all projects. +Offset 01b8h 64-byte drive name. Null-byte terminated + when shorter than 64 chars. + +Song Entry Usage Table +---------------------- +FST 1.10 allows for 99 projects of 99 songs each, giving for +9801 song entries. Each song entry is not necessarily pre- +allocated to any given project; song entry 0 may belong to +project 0, while song entry 1 may belong to another project. +The Song Entry Usage Table provides a quick way to look up +the next free song entry without having to go through all +projects to see which song entries are in use. + +Each bit in the Song Entry Usage Table represents a song. +When 0, the song entry is not in use; when 1, it is. + +Drive Usage Table +----------------- +Each bit in the Drive Usage Table represents a cluster. When 0, the +cluster is free; when 1, the cluster is in use. +32-bit words are filled one by one, least-significant bit first, +until the entire word has the value 0xFFFFFFFF. In other words, the +table starting with the following words have the meaning as described: + +0x1 contains 1 bit on -> first cluster allocated +0x3 contains 2 bits on -> first 2 clusters allocated +0x1f contains 5 bits on -> first 5 clusters allocated +0x1ff contains 9 bits on -> first 9 clusters allocated. + +At the end of the drive usage table, some space seems to be reserved, +possibly representing the backup of the file system info, or something +along those lines. The last 32-bit word of the Drive Usage Table is a +checksum. When all 32-bit words in the entire Drive Usage Table are +summed, the result must be 0. + +Project info +---------------------- +The project info consists of (by default) 99 entries of 512 bytes each. +The actual number of projects is contained by the superblock. + +100 project entries would be 0xc800 bytes. +As projects are numbered starting at 01, a maximum of 99 projects +is possible, giving for 0xc600 bytes. + +How to distinguish between an empty project and an unused project entry? +Answer: Sector 1 (Drive info) contains the project list. + +Projects not mentioned in the drive info project list are empty projects. + +Each project entry has the following layout: + +Offset 0 8-byte project name (obsolete) +Offset 8 4-byte (2 bytes of which are partial project name too) +offset 0ch-0fh Number of songs in use in project +offset 10h-19bh Song info table (a list of 32-bit pointers to the + initial sectors of song info). Length of table should be + 396 bytes for 99 songs per project. + First entry in the table is the last accessed song. + Zero char means unused entry. +Offset 01b8h 64-byte project name. Null-byte terminated if project + name is less than 64 bytes long. + +Song info table +--------------- +The song info table is part of a project entry. It is a list of 32-bit +pointers to sectors containing song info. + +Song info +------------------------ +Song info starts at disk offset 0xee00h, or at +sector 119 (the 120th sector on disk) (depending on +info in superblock). + +Each song entry has a length of 2 sectors and is immediately +followed by 5 sectors of file allocation info. + +Locate points/loops and track slip info is included in the song +entries. + +Offset 00h-03h 32-bit number indicating no. of audio blocks in song +Offset 04h-07h ?0 +Offset 08h-0bh 32-bit number related to audio track interlacing. + + 1/512th of the number of samples per interlace block + before the audio switches to the next track. + + Value of this field equals Cluster size/(tracks*3). + +Offset 0ch-0fh 32-bit number related to audio track interlacing. + + number of sectors per interlace block + before the audio switches to the next track. + + Value of this field equals audio block size + /no. of tracks. + Default audio block size is defined in superblock + (0x480 sectors) + + An audio block size of 0x480 and 2 tracks gives a + block size of 0x240h sectors or 0x48000 bytes + (=294912 bytes). + +Offset 10h-13h Status flags???????????????????? + Offset 0x12h bit 0x10h -> write protect????? + +Offset 28h-2Fh First 8 bytes of song name. + (Maintained for compatibility + with FST before 1.10- + Obsoleted by long filenames + at offset 3b8h) + +Offset 30h ? + +Offset 31h Number of physical tracks used by song. + + Note: + The HD24 has a high sample rate + mode (88200 and 96000 samples per + second, respectively). + + In high sample rate mode, two + physical tracks are used for each + logical track. + + That is, a 12-track song in high + sample rate mode will use 24 tracks + on the machine. The number 24 is + then what is indicated. + + This allows interlacing samples between + tracks for compatibility with systems + running at half the sample rate. + In high sample rate mode, the track layout + is: + physical track 0-1 -> samples of logical track 1 + physical track 2-3 -> samples of logical track 2 + physical track 4-5 -> samples of logical track 3 + .. and so on. Even numbered samples (0,....) + are on even numbered tracks. + +Offset 32h-33h Two more filename characters for short filename, + used in obsolete FST 1.0 standard. + +Offset 34h-36h Sample rate in samples/second + + Typical values are: + + 00h ach 44h -> 44100 Samples/sec + 00h bbh 80b -> 48000 Samples/sec + 01h 58h 88h -> 88200 Samoles/sec + 01h 77h 00h -> 96000 Samples/sec + +Offset 37h Bit depth (18h or 24 by default) + +offset 38h-3bh Unsigned 32-bit number containing + number of samples in song. + + For high sample rates, 2 tracks + are used for each sample; + therefore, a song that according + to this 32-bit number contains 44100 + samples has the same duration at both + 44100 and 88200 kHz. + +offset 3ch Write protect byte. + + This byte contains 8 bits (0-7, where + 7 is the most significant bit and 0 the + least significant bit. In other words + bit 7 has value 128, bit 0 has value 1) + + Bit 2 is on when song is write protected + (value of the byte is 0x4 then), off when + song is write enabled. + +offset 58h-B7h Track slip info for track 1-24 + + Track slip is measured in number of samples. + E.g. for a song recorded at 48 khz, a value + of 480 decimal (0x1e0) means 1/100 second + (10 ms) of track slip. + Track slip is stored as a signed 32-bit number. + Valid values for the HD24 are -170..170 msec + +Offset 0b8h-1e3h Locate point block + +Offset 3b8h-3e7h Full song name, max 64 bytes; + terminated by null byte when less + than 64 bytes + +Offset 400h-???? File allocation info (see below) + +Locate point block +------------------ +The locate point block consists of 24 locate point entries.s + +Locate point entry +------------------ +Each locate point entry has the following layout: +Offset 0-3 32-bit time code + The time code represents the sample number + within the song. +Offset 4-11 The 8-byte locate point name + +Locate point 0 indicates the relative time offset of the +song. This is usually 0, but may be set to other values for +tape transfers. + +The locate point is a 32-bit unsigned integer which contains the +sample number within the song. In other words, in a 44.1 khz +song, the locate point 0:0:1:0 (hours/minutes/seconds/frames) +is encoded as the number 44100. Thus, the locate point furthest +in the song is 2^32=4294967296 samples. +This is enough for 44.1khz songs with a length of 27 hours. + +File allocation info +==================== +The file allocation info consists of file allocation entries. +Each file allocation entry has the following format: + +Offset 00h-03h Starting sector number for audio block +Offset 04h-07h Number of audio blocks in allocation block + +In a valid song, the the 32-bit word on offset 0 of the song +info equals the total sum of the number of audio blocks in the +file allocation info. + +In my disk image, I see songs that had been previously deleted; +the song length in audio blocks is zero for these. This also +goes for songs that have no audio data yet. + +Audio data layout +================= +The audio data of a FST file system is stored in a raw, uncompressed +format. Audio data that consists of multiple channels is interlaced +blockwise (as opposed to sample-by-sample interlacing). + +The data is stored as 24-bit signed little endian integer data. + +The typical audio block size as indicated in the superblock is +0x480 sectors. In stereo audio, each subblock is then 1/2 audio blocks +or 0x240 sectors per channel. + +As the number of tracks increases, the block size per track decreases +proportionally. + +The default audio block size of 0x480 sectors lets itself be divided +into 2,4,6,8,12,16,24 tracks (with a sample size of 24 bit). Each channel +then takes up 0x240, 0x120, 0xc0, 0x90, 0x60, 0x48, 0x30 sectors, +respectively assuming 0x480 blocks per sector. In high sample rate +modes, channels are paired to accomodate for the doubled sample rate. +This is why in high sample rate mode a max of 12 channels are possible, +while the maximum song length is still over 27 hours on 88.2 kHz. + + +Not yet accounted for in this document +====================================== + +How the undo buffer is used (however, this is not relevant because the +undo buffer is cleared after each power off. It might as well exist +in RAM only). + +How pitch info is stored in the songs +auto play +auto rtn +auto rec + +HD24tools extensions to FST +=========================== +An extension is proposed where a song on a HD24 drive is used as data +area, to store non-audio information associated with a song or project. +This would allow HD24 owners to store track notes, mix settings, +protools projects and so on along with their songs. + +A degree of compatibility with the HD24 is desired; although the HD24 +will not be able to use the information, it should also not corrupt it. + +The HD24 does not offer unique file names; moreover, the position of a +file is not constant within the FS. As a result, songs have no unique +identifier that allows other data to be associated with them. + +It is proposed to use bytes 0x3a0-0x3bf of each song entry as unique +identifier. Testing shows that the HD24 recorder does not touch these +bytes, even after a scandisk operation. Moreover, when a song is copied +to another drive, these bytes are copied over as well. + +A single HD24 song would provide ample storage space for most purposes. +Additionally, by using a single song only, the negative impact to the +end user is minimal as no users have ever been registered to actually +create 99 project of 99 songs. To prevent the HD24 from corrupting the +contents of the song, it can be created as 0-track song; previous +experiments have shown that the track count is flexible. Having a song +marked as 0 track prevents the HD24 from arming tracks or playing back +audio from the song, and will give a user some feedback about the nature +of the song, without causing the HD24 to claim that the song is corrupt. +A track count of 0 survives a scandisk command, and it seems that the +HD24 permits copying such songs to other drives. + +A possible way to store data in the song is to have the data song +contain a FAT file system. The advantage of the FAT file system is +that it is well documented, and probably there will be library code +available that will ease the implementation of an embedded FAT +system on HD24 drives. + +The root directory of the file system shall contain a 'songdata' +dir. This data directory shall contain a subdirectory named after the +ID of each song. Of course the file names need to be long enough; if +this is not possible, a map file may be created to contain mappings +from song ID to songname subdirectory ID. + +Data placed in the appropriate songname directory is automatically +associated with the song. Should we so desire, we can also create a +'projdata' directory. + +By keeping the songdata directory structure flat, songs can be moved +across projects without losing their associated files. + 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 @@ +COMPILING HD24TOOLS + +Instructions for Linux (preferably Debian/Ubuntu based): + +Get the source code from svn on HD24tools.com + +sudo 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 + +Note: You may still need to install libflac. + +make clean +./configure +make + +mkdir ~/HD24tools +cp hd24connect ~/HD24tools/ +cp hd24hexview ~/HD24tools/ +cp hd24info ~/HD24tools/ +cp hd24towav ~/HD24tools/ +cp hd24wavefix ~/HD24tools/ +ln -s /usr/lib/libsndfile.so.1 ~/HD24tools/ +ln -s /usr/lib/libportaudio.so ~/HD24tools/ +ln -s /usr/lib/libjack.so ~/HD24tools/ + +For HD24tools to detect the drives (when being run as normal user), +normal users need to have sufficient permissions to work with the +drive device. + +To find out which drive device it is, run HD24connect as root, +and select File->Recovery->Select device... + +This will show you the current device, which is the device +that needs its permissions set. + +You can probably gain device permissions by adding your +regular user to the proper group, making your user the +owner of the device or by setting the device permissions +in /etc/fstab. + 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 @@ +Developing HD24tools +==================== + +To start on development of hd24tools, here are a few tips to get you started. + +Development environment +======================= +You will want libsndfile, libportaudio and the Fast Light Toolkit FLTK to be +present on your system. On Linux you will also want the Jack Audio Connection +Kit (optionally on Mac as well). The targeted compiler is gcc. + +On Windows, development is based on a MSYS/MinGW environment. + +On Mac, XCode is needed, as well as portaudio, libsndfile and FLTK. + +Configuring and building +======================== +Configuration is auto-detected by running + + ./configure + +Building is done with + + make + +Installing is optional. You may want to run the following as root: + + make install + +which will install common binaries to /usr/bin. More interestingly, +you can run + + make installer + +to create the installer for the current platform. Finally, with + + make clean + +you can work from a clean configuration. The configure script also +calls make clean. + +Cross-compiling +=============== +Cross compiling is highly experimental and will probably fail for +most purposes. On linux, you can say + + ./configure os=win32 + +which will attempt to create windows .exe files. However, until +now only hd24hexview.exe has been successfully built on Linux. + + + +./configure +make + +Setup +===== +During configuration, the set of libraries, make files etc to +use is decided by the files in the setup directory. The file +Makefile.in which is located there contains the release number +which must be bumped up for every version. Unless you build +official releases, please add your name to the release number +or make your personal releases otherwise distinguishable from +official releases. + +To perform library detection etc, there are files called +Makefile.setup. in the setup directory. These are +called with various targets to figure out if libraries exist. + +Unless porting to a new platform or adding external libraries, +you will probably rarely need to change most of the setup +scripts. + +File system documentation +========================= +Reverse-engineered information about the ADAT FST file system +can be found in doc/ADATFS.txt. Probably this file contains +enough info to not only allow reading ADAT drives but also to +write them. The biggest obstacle in writing ADAT drives so +far has been to get an accurate LBA sector count of non- +formatted drives on all operating systems. Especially Windows +seems to lack a reliable way to obtain this information. +(Multiplying sectors/cylinders/heads isn't LBA accurate, +any other way known to me is limited to a specific version +of Windows). If you want to contribute to the ADATFS.txt +file, figure out how the FST undo buffers work. To keep this +software free, DO NOT obtain information from Alesis about +FST which might pollute the project with non-free +information. + +The HD24 library +================ +Directory src/lib contains the HD24 library (and other +library source code). + +common.cxx - some common string manipulation functions +convertlib.cpp/.h - conversion between various data types +countsectors.cpp - library to calculate drive size +hd24connect.ico - HD24connect Icon for Windows +hd24devicenamegenerator.cpp/.h - + Library to generate device names that could be + HD24 drives; contains alternatives for all + supported OS platforms +hd24fs.cpp/.h + Library containing definition for HD24 file system + object. + Each file system contains drive info; + The drive info contains 1 or more projects; + Each project contains 0 or more songs; + Each song contains 25 locate points (START + +locate point 1-24) and track slip info for + each track. + + Including hd24fs.h is sufficient to have access to + all of this. + +hd24project.cpp/.h + Library containing hd24 project decoding. + +hd24song.cpp/.h + Library containing hd24 song decoding; + this includes functionality to read audio, set + the song cursor, etc. + +hd24utils.cpp/.h + Library that contains useful routines, such as + printing the hd24 catalog, dumping a header, + saving a drive image etc. that do not belong in + the file system decoding library, + but that multiple programs might have a use for. + +nojack.cpp/.h + Dummy library to replace jack on windows and other + platforms in case it is not present. + +src/lib/FL/ + Native OS file dialog support. + +INSTALLER GENERATOR +=================== + +The code for the installer generator is found in +src/installer. + +Essentially, it takes the compiled binaries of hd24tools, +and converts those to hexdumps in c-source (using an +application called bin2c). This c source is then compiled +and will be able to re-create the original binary +files. + +While no complex registry magic is needed, this is +sufficient for simple installations and probably less work +to figure out than other solutions. + +This was originally intended to create install wizards for Mac, +but ended up being used for Windows only. Mac users seem +comfortable enough with the install-free .dmg images that they +are presented with. + +The install wizard itself is basically implemented as a state +machine. + +The installer for Linux installation could still be made a bit +smoother, specifically in the libraries department- the right +libraries are not always available at the right locations yet. + +THE ACTUAL HD24TOOLS +==================== + +Some tools only have a console/command line version. They are: + +hd24hexview a hex editor +hd24wavefix a program that attempts to recover bit-distorted + audio to something remotely usable again +hd24towav a program that converts raw 24 bit hd24 audio to + wav files +syx2bin a program that converts the HD24 OS .syx files + to binary (not sure if the resulting binaries + are valid) +hd24info a program that prints some info about the hd24 + drives present in the system + +And finally, there is the graphical flagship program of the suite +hd24connect. To start development, it would be recommended to +understand the library, then the command line utilities first. + +The command line tools are in src/ whereas hd24connect is in +src/frontend. + +Originally I intended hd24connect to have a frontend (GUI) and +a backend. As it turned out, the whole thing ended up in the +frontend. If you feel like creating a nice backend so that the +frontend *really* *only* contains GUI stuff, feel free. Sorry. + +The entry point of hd24connect is src/frontend/hd24connect.cpp- +this calls and opens the GUI. + +The main entrance for the GUI is in fluid file ui_hd24connect.fl +(you *really* should use the 'fluid' user interface editor that +comes with fltk to maintain the .fl files). Method make_window +in class UserInterface starts it all. + +TEST SUITE +========== +There is a directory test/ which should at some point contain +regression tests for hd24tools. To make it easier to perform +such tests, it would need to be possible to control hd24tools +entirely in batch-mode (using MIDI for this is may be a +possibile way). + +DOCUMENTATION +============= + +The .pdf documentation may be slightly outdated. If you wish +to update it, you can do so with OpenOffice Writer. + +TASKS +===== +If you want to contribute, here are some things left to do: + +- Write support (realtime vs copy mode) + + Save altered drive/project/song info + + Write support can initially be tested on + drive image files. + + Phase A1: Only overwriting existing audio, but + not allocating new space (copy mode) + + Phase A2: Allocating new space (copy mode) + + Phase B1: realtime write mode with JACK support + +- Wave preview + + This would have to be awfully smart to be able to display + waves with zero active waiting time and without utilizing + peak files. Use information such as screen width reso- + lution to limit the amount of data that needs to be read + from disk. Probably adding a special read mode in the + library could help support this. + +- Figure out how to build (fat) Mac binaries with or without + Mac (but preferrably without requiring both intel and ppc + to build a release that works on either platform) + +- Figuring out a way to write wav header info/session + notes to HD24 songs, while maintaining HD24 compatibility + +- Adding MIDI support to the library (MMC, MTC) + +- Sync to real HD24 recorders? + +- Special HD24tools distro containing ReWire support to + allow streaming audio directly to protools/cubase? + +- Use real LRC to control HD24tools? + +- Figure out OS binary checksum algorithm + +- Create a test suite + +- Figure out how the HD24 performs Undo administration on + the file system level + +- Improve realtime read mode performance for audio streaming + + 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 @@ +Inside the HD24 + +The HD24 is powered by a Motorola Coldfire + +MCF5206EFT54 +K36J +QAJ0435) + +The Ethernet chip is a CrystalLan CS8900A-CQ3, +a 10Base-T LAN chip. + +There is an empty, 26 pin port labelled 'Motorola BDM Port'. +Motorola BDM stands for Motorola Background Debug Module, +so we might speculate that this port allows us to perform +debugging on the HD24 as it is running. + +There are to IC41LV16256 chips in the HD24: according to the +data sheets, they are 256kx16 bit Dynamic RAM with EDO page mode, +giving the HD24 a total of 1 megabyte of RAM. + +There is an ALTERA ACEX EP1K30QC208-2 +FPGA (Field Programmable Gate Array). + +There is a Texas Instruments AHCT16541 +AHCT16541 devices are noninverting 16-bit +buffers composed of two 8-bit sections with +separate output-enable signals. (possibly +used for communication to displays?) + +Analog Devices ADSP 21065L KS-264 +A digital signal processor. + + + 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 @@ +Figuring out on which sector the next recording should start +(or where a crashed live recording starts) +============================================================ +1. Find the start offset of the drive usage table, e.g. 0xa00 +2. Find the suspected start offset of the live recording + in said table. This is the offset of the first 32-bit word + that is 0. + For instance the found offset is 0xe74 +3. This means the recording starts on cluster + 0xe74-0xa00=0x474 +4. The superblock states the number of audio blocks per cluster, + offset 0x14. For the sake of this example, lets assume 9 + audio blocks per cluster. The size of each audio block is on + offset 0x10, usually 0x480. +5. The first audio sector is mentioned on the superblock on + offset 0x7e. In most cases it is 0x1397f6. +6. Each byte in the drive usage table represents 8 clusters. +7. The audio should then start on + 0x1397f6 + (0x480*9*8*(0xe74-0xa00)) = sector 0x5b667f6. + +--------------- +The other way around- calculating offset from sector number: +(0x02e427f6 - 0x1397f6) / 0x480 / clusters /8 + 0xa00 + + 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 @@ +Subject: HD24tools 0.9.0beta for Win32 released +Hello, + +HD24tools version 0.9.0beta has been made available for +the following platforms: + +- Linux (i386) +- Windows (All versions) + +Mac releases are expected to be released soon. + +The most important new features in this release are +- Preliminary write support +- New tabbed GUI +- Several usability enhancements + +The release notes for this and previous release notes can be viewed on +http://ringbreak.dnd.utwente.nl/~mrjb/hd24tools/RELEASE.txt + +As always, the release can be downloaded from: +http://ringbreak.dnd.utwente.nl/~mrjb/hd24tools/download.html + +Should you encounter any problems with this release, +please let me know. + +Best, +Marc + 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 @@ +HD24Connect revision history and roadmap +======================================== + +Implemented features are set in the past tense. A version is complete when all +planned versions are implemented. Until then, sub-versions are used, e.g. +0.3.1 already may have some (but not all) 0.4 features. + +This document ends with suggested features, but is in reverse chronological +order otherwise, and as such starts with features planned for the next +release. + +Current status is somewhere in the middle, search for the text +'CURRENTLY IN PROGRESS' to find out what is being done right now. + +Version 1.1.0 => CURRENTLY IN PROGRESS + +- Added some unit tests to perform automated, scripted testing +- Added frequency/gain display to mixer +- Performed code cleanup: + - Moved recorder, mixer and HD24->PC file transfers + to their own modules + - permit various interfaces (X, Cocoa, Curses, etc) + - possibly permit recording macros? + - permit multi-window interface (show transport/time/mixer + simultaneously) and allow resizing those windows +- Implement batch transports +- Implement realtime recording +- Auto-detect feedback loops! +- Change to multi-window interface to allow viewing multiple tabs at once + (for example both recorder and mixer at same time) +- Implement MIDI control/control surfaces + - Control other MIDI devices with HD24tools + - Control HD24tools with other MIDI devices +- Implement LADSPA support for mixer FX + - Add default GUI for common effects, allow them + to be controlled through control surfaces. +- Implement keyboardless operation +- Add wave viewer for easier selection of export range +- Add functionality to allow changing song naming convention for export +- Simultaneous dual drive support. Benefits: + * allow copying songs between drives + * copying songs/projects from/to drive images +- Add drive images that are found in drive image dir to + drive image dropdown to make it easier to switch between + real and virtual drives +- Implement functionality to signal falling out of record + mode if needed (when drive is full, etc) +- Create an interesting demo drive image to + allow people to play around with it + (low prio: people can download examples from raw-tracks.com + at a $5 fee) + +Version 1.0.0 => Will remain in alpha + +- Made source code available to the general public +- Added recovery feature to deal with a specific class of + 'unexpected end of song' error on fragmented drives +- Added block checksum calculation to library +- Implemented saving of changed project name/song name to disk +- Added code for cluster allocation +- Added code for converting orphan clusters to allocation entries +- Compiling framework was changed to allow smoother Mac compiles +- Added mixer tab with save/load mixer settings functionality +- Finished up restructuring of mixer to make it work again +- Added save functionality to allow renaming drive +- Made detection of corrupted drives smoother to prevent need for + http://ringbreak.dnd.utwente.nl/~mrjb/hd24tools/drivenumber.html +- Added Check for 'forbidden characters' in filenames + \ / : * ? " < > | + (HD24 accepts these but can have unpredictable effects on + OS side) +- Added allocating functionality to allow lengthening songs + automatically during transfer +- Altered layout of drive catalog to fit longer song names + and to have a bit larger margin on the left for printing +- Added functionality to allow 1-click toggle between + sample rates of 44.1 <=> 48 kHz and 88.2 <=> 96 kHz + (toggling between lower/higher sample rates is not possible + without conversion as higher sample rates use 2 recording + tracks per channel). +- Added dialog for simpler 'headerless' live recording recovery +- Implemented initial headerless live recovery scheme +- Made headerless live recording recovery read-only +- Added functionality to create empty drive images +- Created dialog for setting song parameters +- Implemented Mixer JACK support +- Implemented framework for smarter library loading. + This should allow Mac (and even Windows) users to have + JACK functionality, and will no longer require Mac + users to startup HD24connect by running an AppleScript. +- ... and made library smart loading even smarter by letting + it look in the program directory first, the PATH dir next, + and all usual library directories next. This should result + in library loading that Just Works in most cases and + will allow JACK support on all platforms. +- Wrote documentation explaining how to build HD24tools + from source (Linux, 64-bit Athlon) +- Added functionality to create projects +- Added functionality to create songs (incl. superblock + song count update) +- Made sure changes in song/drive/project names also reflect + properly in FST 1.00 drives +- Added functionality to automatically pre-record silence + in songs on creating them +- Added functionality to update song usage list after + song creation +- Automatically select song as 'default' after creation +- Implemented reload of drive list/catalog/project list/song list + after major write operations +- User interface settings reloaded as appropriate after writing + to drive +- Added options dialog to allow (among other things) specifying + a filename pattern for file transfers to PC +- Made write-protect checkbox work +- Added drive format functionality +- Added functionality to delete songs +- Added functionality to delete projects +- Made 'bypass' button for mixer work +- Added timeout-style messages to alpha display +- Implemented functionality to display song information + on alpha display +- Implemented functionality for sorting songs inside a project. + This allows easily reordering songs by renaming them. +- Implemented SMPTE timecode striping- for now limited to + 30fps nondrop starting at 00:00:00.00. + May not work on sample rates other than 48kHz. In fact, + it may not work at all. +- Made sure superblock is updated with number of free clusters + after song transfer to HD24 drive/creation of new song +- Implemented write-protect to prevent writing to drives when + working with header files. +- Implemented functionality to reduce number of sectors read + when transferring fewer tracks. The expected performance + win is not very big as the number of drive seeks is about + the same, but the weight of the added logic is minimal. + Perhaps on some systems the difference is noticable. YMMV. +- Implemented .wav writing without libsndfile. If it is missing, + you'll still be able to transfer such files to your computer. +- Made sure write functionality is disabled for drives found + not to be valid HD24 drives (due to corruption, or perhaps + they're simply OS drives which we DEFINITELY don't want to + overwrite) +- Implemented locate point saving +- Implemented (preliminary) transfer-time mixing of tracks +- Made sure song/project are made default after selecting them +- Fixed a non critical bug where closing the program during + playback caused a crash. + +TODO: Bugs to fix: + +- After quickformat of a drive, catalog and related screens are + not updated. + +TO DO: Testing and packaging: + +- Fixme: update all of drive info page on refresh + (What's missing?) +- Make sure that 'new folder' button works properly on + all platforms! (Fixed on Windows, TO DO on mac) +- Distribute Mac version as Universal Binary +- Finally get .aif, .sd2 and .dig/.sd to work properly! +- Check all FIXME and TODO comments in code +- Get 16-bit export to work (low priority) +- Documentation + +Version 0.9.0 + +- Implemented tabbed interface +- Added functionality to export drive images +- Added time stamp to catalog +- Added drive catalog display to drive inforrmation +- Changed default time display to 30 frames per second instead of 1/100 sec + +- Added the 'Recorder' with various new features +- Proper solo/mute buttons instead of solo/mute by channel selection +- Track arm buttons +- 24-channel display faithfully emulating what the HD24 would show +- Peak modes: No peak hold, momentary peak hold, continuous peak hold +- Added locate slider to rapidly jump to any point in the song +- Added punch in/out locate points +- Added visual clue to transport controls showing that clicking 'set' + can set locate points +- Added input monitoring (mainly Linux) +- Added dropdown to map stereo inputs to channel pairs in various ways +- Fancy 7-segment LED display +- Equally fancy info display +- Fancy, bigger graphical buttons with LED for transport control +- Fixed a clipping bug in portaudio playback (playback only) + +- Added signal detection to track selection in transfer tab +- Added dropdown to allow a flexible custom size limit for exported files +- Added dropdown to stamp songs with a different sample rate + +- Added tab for transfer back to HD24 +- Added functionality that permits selecting many files at once +- Added functionality to automatically spread multi-track files + across several HD24 tracks +- Added functionality to automatically mix multi-track files to mono +- Added functionality to allow erasing tracks +- Added functionality to allow moving tracks (including track action) + up or down +- Added functionality to clear filenames from tracks +- Added functionality to overwrite existing audio with audio from a file. + Many file formats are supported (subject to what is supported by + libsndfile). +- SD2 file format support (does this work now?) +- Create new folder from file browse dialog (does this work now?) + + +Version 0.8.2 + +- Hardened the software in some places to be more crash-resistant + in handling corrupt drives +- Some compatibility enhancements +- Fixed a bug in the calculation of the total number of bytes to export, + which caused the auto-split popup not to be displayed in some cases. + +Version 0.8.1 + +- Fixed bug that caused auto-split popup to always appear for long recordings, + even if only a small fragment was being exported. + +Version 0.8.0 + +- Printing disk contents on paper and file +- Entirely replaced export engine for faster exports +- Created OS native installers. +- Allow transferring multiple songs at once (song choice 'All Songs') +- Added possibility to export to stereo and multi-track files. + +Version 0.7 + +- This never-released version adds high samplerate support. + +Version 0.6.2 + +- Fixed a bug that caused the Windows version to lock up when loading a header file +- Initial release for MacOS/X 10.4 + +Version 0.6.1 + +- Fixed a bug in the drive name generation in Windows + +Version 0.6 + +- Initial Macintosh OS/X port. Still flaky due to interesting behavior of packages that HD24connect depends on. +- Relabeled button "Transfer to PC" as "Transfer to Mac" for OS/X version. +- Fixed bug that cleared surface of cancel button during transfers. +- Added warning dialog to improve user friendliness when no HD24 drive is detected on program startup +- Added menu option 'File/Detect HD24 drives' to allow re-scanning for drives after program startup. +- Project directory browser now uses OS native file dialog. +- Added menu option to allow creating header files from within hd24connect +- Removed portaudio dependency (this has no visible impact). +- Added Estimated Time of Arrival in transfers +- Removed dependency on command line options to enable recovery features +- Added application (desktop) icon for Windows +- Allow exporting to more different file formats (currently WAV and AIFF) +- Altered file naming for export +- Cleaned up code that deals with drive name generation +- Version control is now in place, allowing multiple people to work + on the project at the same time (Welcome, Randy!) + +Version 0.5 + +- Added --force feature to allow using hd24 disks with invalid MBR. +- Added --header feature which allows to use a fixed header file along with + a corrupt disk. This permits us to recover audio without need to modify + data on the corrupted disk. +- Added portaudio playback. For the Windows version this means that audio + preview is now supported, while under Linux the Jack Audio Connection Kit + is no longer required for audio preview. +- Fixed a bug in Linux audio preview. This minor bug affected exactly + 1 user (me). +- Added dialog to allow renaming drives, projects and songs (in memory only) +- Altered project handling to more easily allow in-memory edits of projects + +Version 0.4 + +- Fixed a minor bug with the file write caching. +- Added a button to allow the user to interrupt a transfer. +- Fixed flakyness in audio playback +- Added dialog to allow manually setting locate points +- Fix bug which causes windows version not to display song names +- Added feature to allow setting loop start/end during playback +- Implemented export to wav (for now, instead of raw) using libsndfile +- Implemented basic loop mode for audio playback. + +Version 0.3 + +- Added file write caching to speed up export under Windows. +- Added direct playing under Linux (still flaky) +- Altered library to resolve issue with STL string memory leaks + +Version 0.2 + +- Added support for locate points. +- Added backwards export. +- Initial windows version. + +Version 0.1 + +- First workable version. + +HD24hexview revision history and roadmap +======================================== + +Future + +- Verify/Fix any remaining issues with 4 GB limit on Windows +- Correctly determine drive size +- Allow multi-sector paste (from file). + +Version 1.4beta + +- Replaced code for windows drive size detection. + +Version 1.3beta + +- Added expert mode as safety switch to prevent accidentally writing to disk. +- In expert mode, added a big fat warning for writing to the default boot + disk (/dev/hda or \\.\PHYSICALDRIVE0) and a (not so big & fat, but still) + warning for writing to other devices. + +Version 1.2beta + +- Added d- feature to dump sector counting from end of disk + This allows dumping the last sector from disk without having to figure + out the number of sectors based on brand and model of the disk. + Unfortunately, this does not work properly yet for Windows devices. + +Version 1.1beta + +- Fixed a bug in windows version that required output file to already exist + before writing +- Added single-sector checksum (no multi-sector checksum yet) + +Version 1.0beta + +- Implemented compare +- Implemented write offset + +Version 0.3 + +- Implemented edit and write back of sectors +- Implemented single-sector paste +- Ported to Windows +- Resolved a 4 GB issue with windows version +- Allowed using files as devices + +Version 0.2 + +- Implemented support for setting blocks +- Resolved 4 gigabyte limitation for linux +- Implemented scan +- Implemented write to file + +Version 0.1 +- Implemented code to autodetect HD24 disks +- Implemented feature to navigate disks with +/-/o + +======================================================== +Version x.x + +Spare ideas/suggested future features: + +- 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. + + Will not be implemented anytime soon; this scenario is too + rare. Also, should recovery be needed, other ways exist to do so. + +- Allow the program to use installed audio encoders to + encode to mp3/flac/etc + +- Time line/draggable export locators + + Proposed is a graphical display to allow + visually setting locate points for export. + Alternatively, a 'scrub editor' style display would be + workable. + While interesting, it would be rather time consuming + to build such a time line. For now, a draggable slider + is made available to ease the pain a bit. + +- Check available drive size before export + + I'm not sure if I already implemented this. Obviously, + it is a required feature. + +- Allow transferring multiple projects at once + (project choice 'All projects') + + Will probably be implemented at some point, but + custom song naming convention is then required first. + +- Allow automatic deletion of files when transfer is interrupted + +- Normalizing audio as it is being exported + + This will require analyzing the entire export range + prior to export (possibly more, if the export is a + single song of an entire live performance; it is likely + that we'd want to normalize the whole performance + equally. + +- Allow exporting to different bit depths +- MIDI control (both controlling HD24tools via MIDI or + let HD24tools control HD24 recorder via MIDI). + + The benefit of allowing HD24tools control via MIDI + is that frequently requested functionality that the + HD24 does not support is a possibility; for instance, + the HD24 does not allow selecting songs via MIDI, + whereas such implementation in HD24tools would be + a fairly simple matter once it is MIDI enabled. + Someone also mentioned that possibily a recording + log could be kept by HD24tools when connected to + a HD24 via MIDI by simply keeping track of record + events. Unfortunately the HD24 does not send MIDI + for track record enable, even though it supports + track arming via MIDI (the good news is that some + MIDI functionality is supported even though the + HD24 itself does not send out MIDI for those actions). + +- Storing metadata on HD24 drives + + There are some possibilities for this. One way is + to create a song contaning (for instance) a FAT + file system, and using some unused space in the + song entries to allow entries in that FAT file + system to uniquely point to them; this would allow + storing song-unique info (such as track data, etc) + in that file system. + +- Locate points in directory listing + + This would make the catalog file a fair bit longer. + As such it would have to be an option that could + be turned on/off. + +- Virtual BRC application + + This would be limited to whatever MMC supports. + +- Copying projects +- Batch transfer +- One click drive backup + + These all come down to the same thing: find a + way to not require user intervention while + transferring large amounts of data. + Perhaps a 2-click drive backup (with the possibility + to edit the batch before export) is more useful than + a 1-click backup. + The main benefit (not having to wait actively while + audio is being transferred) is the same. + +- Calculate approx. occupied drive space per song, and add + to catalog. + +- Display currently selected song/project on other tabs as + well + - current song is now displayed on alpha display. + +- Allow different UIs (proposed is command line interface, + non-X interface, Cocoa interface, ...) + +- Control surface support, to allow using MIDI-enabled + consoles to control the HD24tools mixer/recorder + +- Add Vista tip to manual (regarding admin account for write + support) + Also add this info: + http://tech.groups.yahoo.com/group/hd24/message/12102 + 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 @@ +SYX file format +=============== +The SYX file format packs every 7 8-bit bytes of a binary file +into 8 7-bit bytes, which allows for a MIDI compatible file. +These files can be converted to true binary files using the +hd24syx2bin utility. + +Once converted, the format seems to be as follows: + +byte 0x00-0x07: string 'HD24CODE' +byte 0x08-0x0b: unknown (checksum?) +byte 0x0c-0x0f: version number string (e.g. "1.20") +byte 0x10-0x13: 32-bit word, value 0 +byte 0x14-0x1b: Release date string (MM/DD/YY) +byte 0x1c-0x1f: 32-bit word, value 0 +byte 0x20-0x27: Build time (hh:mm:ss) +byte 0x28-0x2b: 32-bit word, value 0 +byte 0x2c-0x2f: binary file length in byte. + for version 1.20, file length is + 712736 so bytes 0x2c-0x2f are + 0xae020 or 0x00, 0x0a, 0xe0, 0x20 + 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 @@ +Testplan for HD24tools + +Hexview +- startup without HD24 drive connected +- startup with HD24 connected +- 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 +of song, corrupt header, etc) +- startup with --dev and --force +- Specific to hexview: d-1 (sectorcount relative to end of disk) + How much time does the detection take under windows? + +HD24connect: +- startup without HD24 drive connected +- startup with 1 HD24 drive connected +- startup with multiple HD24 drives connected +- startup with --dev option (device node and image file, respectively) +- ... ditto, AND with/without an HD24 drive connected +- startup with both --dev en --force options +- As above, but by selecting these options from the GUI +- And again. Any irregularities? +- Irregularities with drives/images containing: + 0, 1, more projects? 99 projects? +- Irregularities with projects containing + 0, 1, more songs? 99 songs? +- Irregularities when selecting songs with: + 0 length? + 0 tracks? (is this possible?) +- Irregularities when selecting option '--All songs--' ? +- Irregularities on renaming drive/project/song? +- Does the 'new folder' button work while browsing the project directory? + +Exporting: +- HD24connect should detect when the exportdirectory does not (or no longer) + exist when the export transfer is started. + +Special cases: +- Exporting a song with zero length +- Exporting 0 samples +- Exporting 1 sample +- Exporting > 2GigaSamples +- Auto split enabled/disabled + +Test for all sample rates: +- What name is being used (renamed or not?) +- Full songs in all formats +- Export all tracks +- Export 0 tracks +- Export only track 1, track 2, ... track N (n=number of tracks) +- Songs > 2 GiB/track (to test automatic splitting) +- Start locpoint=START, end locpoint=END +- start locpoint=START, end locpoint=2 samples +- start locpoint=START, end locpoint=10 sec +- start locpoint=1 sec, end locpoint=10 sec +- start locpoint=END, end locpoint=START +- start locpoint=1 sample, end locpoint=END +- start locpoint=1 sample, end locpoint=2 samples +- start locpoint=1 sample, end locpoint=10 sec +- start locpoint=1 sample, end locpoint=END +- start locpoint=1 sec, end locpoint=END + +Select song 'All songs' on a drive not containing double songnames, +export to an empty directory. +- No questions are asked regarding overwriting files. +- Nothing is mentioned about double song names (or prefixing song names). +- HD24connect correctly detects if any songs with those prefixes already exist. +- Are existing filenames properly detected when exporting large files (that + need splitting)? e.g. files with suffix _part1, _part2. + +TRANSPORT CONTROL/audio preview +- To be tested on songs of either high or low sample rates +- All possible state changes: stop->play, play->stop, etc. +- Set locatepoints +- Loop mode +- Drag locate bar +- FF past end of song possible? (by changing songs? by using JACK?) +- REW to negative time code possible? (by using Jack?) +- Change song during playback, including the possibility of changing song + at a time code not present in both songs +- Export audio during playback could cause audio to sound choppy but the exported audio should be OK. + +RECOVERY FEATURES +- Creating a drive image: + - What happens if there isn't enough drive space to hold the image? +- Load created drive image and use it as HD24 drive +- If this drive image is opened (File->open drive image), and we select + file->recovery->select device, the filename of the current drive image + should be reported as current device. +- Switch device +- Loading longliverec header: Can audio be exported correctly? (is it similar/ + equal to the audio of the audio preview? +- For both high and low sample rates? +- Selecting a non-HD24 drive as drive image (for instance a random file, + or windos drive) should not cause HD24tools to crash during playback or + export. + +Other features +- 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. + +TRANSFER TO HD24 DRIVE +Tests to run that do not perform allocation: +- Start transfer without files +- With 1 file (in first slot) +- With 1 file (in 2nd slot, in last slot) (using a clean image) +- With 1 file (in 2nd slot, in last slot) (using an image with track 1 in use) +- 16 track song/24 track song +- With multiple files, less than the number of tracks +- With multiple files, equal to the number of tracks +- with files smaller than the song size +- with files equal to the song size +- with files larger than the song size +- with multi channel files +- with files that have a different sample rate +- with files that have a different bit depth +- with several files of various formats at once + +Tests that do perform allocation: +- Start with an empty song +- Transfer a file with 0 length to HD24 +- Transfer a file with >0 length to HD24 +- Transfer a file with even greater length to HD24 +- Create another song, transfer some audio to it. + Is start of song cluster word-aligned in usage table? +- Extend the first song. Does this work right? + Is the continuation of the song word-aligned? +- What happens if the file to transfer is longer than + the remaining amount of drive space? + + + + diff --git a/doc/artwork/DMG_Background.png b/doc/artwork/DMG_Background.png new file mode 100644 index 0000000..720305d Binary files /dev/null and b/doc/artwork/DMG_Background.png differ diff --git a/doc/artwork/DMG_Background.psd b/doc/artwork/DMG_Background.psd new file mode 100644 index 0000000..6c648b2 Binary files /dev/null and b/doc/artwork/DMG_Background.psd differ diff --git a/doc/artwork/HD24Connect.icns b/doc/artwork/HD24Connect.icns new file mode 100644 index 0000000..17714bb Binary files /dev/null and b/doc/artwork/HD24Connect.icns differ diff --git a/doc/artwork/HD24_vipower.jpg b/doc/artwork/HD24_vipower.jpg new file mode 100644 index 0000000..b667e9d Binary files /dev/null and b/doc/artwork/HD24_vipower.jpg differ diff --git a/doc/artwork/Icon.psd b/doc/artwork/Icon.psd new file mode 100644 index 0000000..77f35a6 Binary files /dev/null and b/doc/artwork/Icon.psd differ diff --git a/doc/artwork/hd24connect.jpg b/doc/artwork/hd24connect.jpg new file mode 100644 index 0000000..e6d0695 Binary files /dev/null and b/doc/artwork/hd24connect.jpg differ diff --git a/doc/artwork/hd24display.png b/doc/artwork/hd24display.png new file mode 100644 index 0000000..c701008 Binary files /dev/null and b/doc/artwork/hd24display.png differ diff --git a/doc/artwork/hd24pc.jpg b/doc/artwork/hd24pc.jpg new file mode 100644 index 0000000..70b0278 Binary files /dev/null and b/doc/artwork/hd24pc.jpg differ diff --git a/doc/hd24tools_manual.odt b/doc/hd24tools_manual.odt new file mode 100644 index 0000000..691bd94 Binary files /dev/null and b/doc/hd24tools_manual.odt differ diff --git a/doc/hd24tools_manual.pdf b/doc/hd24tools_manual.pdf new file mode 100644 index 0000000..cbb32ff Binary files /dev/null and b/doc/hd24tools_manual.pdf differ diff --git a/images/longliverec.h24 b/images/longliverec.h24 new file mode 100644 index 0000000..e6fe746 Binary files /dev/null and b/images/longliverec.h24 differ diff --git a/images/unquickformat.h24 b/images/unquickformat.h24 new file mode 100644 index 0000000..1d6c130 Binary files /dev/null and b/images/unquickformat.h24 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 @@ +-0 Backup superblock 1 +d0 +bb +be +d-01 +p +ws +-0 Backup Drive info 1 +d01 +bb +be +d-02 +p +ws +-0 Backup undo (?) usage 1 +d02 +bb +be +d-05 +p +ws +d03 +bb +be +d-04 +p +ws +d04 +bb +be +d-03 +p +ws +-0 Backup drive usage table 1 +d05 +bb +be +d-14 +p +ws +d06 +bb +be +d-13 +p +ws +d07 +bb +be +d-12 +p +ws +d08 +bb +be +d-11 +p +ws +d09 +bb +be +d-10 +p +ws +d0A +bb +be +d-0F +p +ws +d0B +bb +be +d-0E +p +ws +d0C +bb +be +d-0D +p +ws +d0D +bb +be +d-0C +p +ws +d0E +bb +be +d-0B +p +ws +d0F +bb +be +d-0A +p +ws +d10 +bb +be +d-09 +p +ws +d11 +bb +be +d-08 +p +ws +d12 +bb +be +d-07 +p +ws +d13 +bb +be +d-06 +p +ws +-0 Backup project 1 +d14 +bb +be +d-15 +p +ws +-0 Backup project 2 +d15 +bb +be +d-16 +p +ws +-0 Backup project 3 +d16 +bb +be +d-17 +p +ws +-0 Backup project 4 +d17 +bb +be +d-18 +p +ws +-0 Backup project 5 +d18 +bb +be +d-19 +p +ws +-0 Backup project 6 +d19 +bb +be +d-1A +p +ws +-0 Backup project 7 +d1A +bb +be +d-1B +p +ws +-0 Backup project 8 +d1B +bb +be +d-1C +p +ws +-0 Backup project 9 +d1C +bb +be +d-1D +p +ws +-0 Backup project 10 +d1D +bb +be +d-1E +p +ws +-0 Backup project 11 +d1E +bb +be +d-1F +p +ws +-0 Backup project 12 +d1F +bb +be +d-20 +p +ws +-0 Backup project 13 +d20 +bb +be +d-21 +p +ws +-0 Backup project 14 +d21 +bb +be +d-22 +p +ws +-0 Backup project 15 +d22 +bb +be +d-23 +p +ws +-0 Backup project 16 +d23 +bb +be +d-24 +p +ws +-0 Backup project 17 +d24 +bb +be +d-25 +p +ws +-0 Backup project 18 +d25 +bb +be +d-26 +p +ws +-0 Backup project 19 +d26 +bb +be +d-27 +p +ws +-0 Backup project 20 +d27 +bb +be +d-28 +p +ws +-0 Backup project 21 +d28 +bb +be +d-29 +p +ws +-0 Backup project 22 +d29 +bb +be +d-2A +p +ws +-0 Backup project 23 +d2A +bb +be +d-2B +p +ws +-0 Backup project 24 +d2B +bb +be +d-2C +p +ws +-0 Backup project 25 +d2C +bb +be +d-2D +p +ws +-0 Backup project 26 +d2D +bb +be +d-2E +p +ws +-0 Backup project 27 +d2E +bb +be +d-2F +p +ws +-0 Backup project 28 +d2F +bb +be +d-30 +p +ws +-0 Backup project 29 +d30 +bb +be +d-31 +p +ws +-0 Backup project 30 +d31 +bb +be +d-32 +p +ws +-0 Backup project 31 +d32 +bb +be +d-33 +p +ws +-0 Backup project 32 +d33 +bb +be +d-34 +p +ws +-0 Backup project 33 +d34 +bb +be +d-35 +p +ws +-0 Backup project 34 +d35 +bb +be +d-36 +p +ws +-0 Backup project 35 +d36 +bb +be +d-37 +p +ws +-0 Backup project 36 +d37 +bb +be +d-38 +p +ws +-0 Backup project 37 +d38 +bb +be +d-39 +p +ws +-0 Backup project 38 +d39 +bb +be +d-3A +p +ws +-0 Backup project 39 +d3A +bb +be +d-3B +p +ws +-0 Backup project 40 +d3B +bb +be +d-3C +p +ws +-0 Backup project 41 +d3C +bb +be +d-3D +p +ws +-0 Backup project 42 +d3D +bb +be +d-3E +p +ws +-0 Backup project 43 +d3E +bb +be +d-3F +p +ws +-0 Backup project 44 +d3F +bb +be +d-40 +p +ws +-0 Backup project 45 +d40 +bb +be +d-41 +p +ws +-0 Backup project 46 +d41 +bb +be +d-42 +p +ws +-0 Backup project 47 +d42 +bb +be +d-43 +p +ws +-0 Backup project 48 +d43 +bb +be +d-44 +p +ws +-0 Backup project 49 +d44 +bb +be +d-45 +p +ws +-0 Backup project 50 +d45 +bb +be +d-46 +p +ws +-0 Backup project 51 +d46 +bb +be +d-47 +p +ws +-0 Backup project 52 +d47 +bb +be +d-48 +p +ws +-0 Backup project 53 +d48 +bb +be +d-49 +p +ws +-0 Backup project 54 +d49 +bb +be +d-4A +p +ws +-0 Backup project 55 +d4A +bb +be +d-4B +p +ws +-0 Backup project 56 +d4B +bb +be +d-4C +p +ws +-0 Backup project 57 +d4C +bb +be +d-4D +p +ws +-0 Backup project 58 +d4D +bb +be +d-4E +p +ws +-0 Backup project 59 +d4E +bb +be +d-4F +p +ws +-0 Backup project 60 +d4F +bb +be +d-50 +p +ws +-0 Backup project 61 +d50 +bb +be +d-51 +p +ws +-0 Backup project 62 +d51 +bb +be +d-52 +p +ws +-0 Backup project 63 +d52 +bb +be +d-53 +p +ws +-0 Backup project 64 +d53 +bb +be +d-54 +p +ws +-0 Backup project 65 +d54 +bb +be +d-55 +p +ws +-0 Backup project 66 +d55 +bb +be +d-56 +p +ws +-0 Backup project 67 +d56 +bb +be +d-57 +p +ws +-0 Backup project 68 +d57 +bb +be +d-58 +p +ws +-0 Backup project 69 +d58 +bb +be +d-59 +p +ws +-0 Backup project 70 +d59 +bb +be +d-5A +p +ws +-0 Backup project 71 +d5A +bb +be +d-5B +p +ws +-0 Backup project 72 +d5B +bb +be +d-5C +p +ws +-0 Backup project 73 +d5C +bb +be +d-5D +p +ws +-0 Backup project 74 +d5D +bb +be +d-5E +p +ws +-0 Backup project 75 +d5E +bb +be +d-5F +p +ws +-0 Backup project 76 +d5F +bb +be +d-60 +p +ws +-0 Backup project 77 +d60 +bb +be +d-61 +p +ws +-0 Backup project 78 +d61 +bb +be +d-62 +p +ws +-0 Backup project 79 +d62 +bb +be +d-63 +p +ws +-0 Backup project 80 +d63 +bb +be +d-64 +p +ws +-0 Backup project 81 +d64 +bb +be +d-65 +p +ws +-0 Backup project 82 +d65 +bb +be +d-66 +p +ws +-0 Backup project 83 +d66 +bb +be +d-67 +p +ws +-0 Backup project 84 +d67 +bb +be +d-68 +p +ws +-0 Backup project 85 +d68 +bb +be +d-69 +p +ws +-0 Backup project 86 +d69 +bb +be +d-6A +p +ws +-0 Backup project 87 +d6A +bb +be +d-6B +p +ws +-0 Backup project 88 +d6B +bb +be +d-6C +p +ws +-0 Backup project 89 +d6C +bb +be +d-6D +p +ws +-0 Backup project 90 +d6D +bb +be +d-6E +p +ws +-0 Backup project 91 +d6E +bb +be +d-6F +p +ws +-0 Backup project 92 +d6F +bb +be +d-70 +p +ws +-0 Backup project 93 +d70 +bb +be +d-71 +p +ws +-0 Backup project 94 +d71 +bb +be +d-72 +p +ws +-0 Backup project 95 +d72 +bb +be +d-73 +p +ws +-0 Backup project 96 +d73 +bb +be +d-74 +p +ws +-0 Backup project 97 +d74 +bb +be +d-75 +p +ws +-0 Backup project 98 +d75 +bb +be +d-76 +p +ws +-0 Backup project 99 +d76 +bb +be +d-77 +p +ws +-0 Backup song 1 +d77 +bb +be +d-79 +p +ws +d78 +bb +be +d-78 +p +ws +-0 Backup song alloc info 1 +d79 +bb +be +d-7E +p +ws +d7A +bb +be +d-7D +p +ws +d7B +bb +be +d-7C +p +ws +d7C +bb +be +d-7B +p +ws +d7D +bb +be +d-7A +p +ws +-0 Backup song 2 +d7E +bb +be +d-80 +p +ws +d7F +bb +be +d-7F +p +ws +-0 Backup song alloc info 2 +d80 +bb +be +d-85 +p +ws +d81 +bb +be +d-84 +p +ws +d82 +bb +be +d-83 +p +ws +d83 +bb +be +d-82 +p +ws +d84 +bb +be +d-81 +p +ws +-0 Backup song 3 +d85 +bb +be +d-87 +p +ws +d86 +bb +be +d-86 +p +ws +-0 Backup song alloc info 3 +d87 +bb +be +d-8C +p +ws +d88 +bb +be +d-8B +p +ws +d89 +bb +be +d-8A +p +ws +d8A +bb +be +d-89 +p +ws +d8B +bb +be +d-88 +p +ws +-0 Backup song 4 +d8C +bb +be +d-8E +p +ws +d8D +bb +be +d-8D +p +ws +-0 Backup song alloc info 4 +d8E +bb +be +d-93 +p +ws +d8F +bb +be +d-92 +p +ws +d90 +bb +be +d-91 +p +ws +d91 +bb +be +d-90 +p +ws +d92 +bb +be +d-8F +p +ws +-0 Backup song 5 +d93 +bb +be +d-95 +p +ws +d94 +bb +be +d-94 +p +ws +-0 Backup song alloc info 5 +d95 +bb +be +d-9A +p +ws +d96 +bb +be +d-99 +p +ws +d97 +bb +be +d-98 +p +ws +d98 +bb +be +d-97 +p +ws +d99 +bb +be +d-96 +p +ws +-0 Backup song 6 +d9A +bb +be +d-9C +p +ws +d9B +bb +be +d-9B +p +ws +-0 Backup song alloc info 6 +d9C +bb +be +d-A1 +p +ws +d9D +bb +be +d-A0 +p +ws +d9E +bb +be +d-9F +p +ws +d9F +bb +be +d-9E +p +ws +dA0 +bb +be +d-9D +p +ws +-0 Backup song 7 +dA1 +bb +be +d-A3 +p +ws +dA2 +bb +be +d-A2 +p +ws +-0 Backup song alloc info 7 +dA3 +bb +be +d-A8 +p +ws +dA4 +bb +be +d-A7 +p +ws +dA5 +bb +be +d-A6 +p +ws +dA6 +bb +be +d-A5 +p +ws +dA7 +bb +be +d-A4 +p +ws +-0 Backup song 8 +dA8 +bb +be +d-AA +p +ws +dA9 +bb +be +d-A9 +p +ws +-0 Backup song alloc info 8 +dAA +bb +be +d-AF +p +ws +dAB +bb +be +d-AE +p +ws +dAC +bb +be +d-AD +p +ws +dAD +bb +be +d-AC +p +ws +dAE +bb +be +d-AB +p +ws +-0 Backup song 9 +dAF +bb +be +d-B1 +p +ws +dB0 +bb +be +d-B0 +p +ws +-0 Backup song alloc info 9 +dB1 +bb +be +d-B6 +p +ws +dB2 +bb +be +d-B5 +p +ws +dB3 +bb +be +d-B4 +p +ws +dB4 +bb +be +d-B3 +p +ws +dB5 +bb +be +d-B2 +p +ws +-0 Backup song 10 +dB6 +bb +be +d-B8 +p +ws +dB7 +bb +be +d-B7 +p +ws +-0 Backup song alloc info 10 +dB8 +bb +be +d-BD +p +ws +dB9 +bb +be +d-BC +p +ws +dBA +bb +be +d-BB +p +ws +dBB +bb +be +d-BA +p +ws +dBC +bb +be +d-B9 +p +ws +-0 Backup song 11 +dBD +bb +be +d-BF +p +ws +dBE +bb +be +d-BE +p +ws +-0 Backup song alloc info 11 +dBF +bb +be +d-C4 +p +ws +dC0 +bb +be +d-C3 +p +ws +dC1 +bb +be +d-C2 +p +ws +dC2 +bb +be +d-C1 +p +ws +dC3 +bb +be +d-C0 +p +ws +-0 Backup song 12 +dC4 +bb +be +d-C6 +p +ws +dC5 +bb +be +d-C5 +p +ws +-0 Backup song alloc info 12 +dC6 +bb +be +d-CB +p +ws +dC7 +bb +be +d-CA +p +ws +dC8 +bb +be +d-C9 +p +ws +dC9 +bb +be +d-C8 +p +ws +dCA +bb +be +d-C7 +p +ws +-0 Backup song 13 +dCB +bb +be +d-CD +p +ws +dCC +bb +be +d-CC +p +ws +-0 Backup song alloc info 13 +dCD +bb +be +d-D2 +p +ws +dCE +bb +be +d-D1 +p +ws +dCF +bb +be +d-D0 +p +ws +dD0 +bb +be +d-CF +p +ws +dD1 +bb +be +d-CE +p +ws +-0 Backup song 14 +dD2 +bb +be +d-D4 +p +ws +dD3 +bb +be +d-D3 +p +ws +-0 Backup song alloc info 14 +dD4 +bb +be +d-D9 +p +ws +dD5 +bb +be +d-D8 +p +ws +dD6 +bb +be +d-D7 +p +ws +dD7 +bb +be +d-D6 +p +ws +dD8 +bb +be +d-D5 +p +ws +-0 Backup song 15 +dD9 +bb +be +d-DB +p +ws +dDA +bb +be +d-DA +p +ws +-0 Backup song alloc info 15 +dDB +bb +be +d-E0 +p +ws +dDC +bb +be +d-DF +p +ws +dDD +bb +be +d-DE +p +ws +dDE +bb +be +d-DD +p +ws +dDF +bb +be +d-DC +p +ws +-0 Backup song 16 +dE0 +bb +be +d-E2 +p +ws +dE1 +bb +be +d-E1 +p +ws +-0 Backup song alloc info 16 +dE2 +bb +be +d-E7 +p +ws +dE3 +bb +be +d-E6 +p +ws +dE4 +bb +be +d-E5 +p +ws +dE5 +bb +be +d-E4 +p +ws +dE6 +bb +be +d-E3 +p +ws +-0 Backup song 17 +dE7 +bb +be +d-E9 +p +ws +dE8 +bb +be +d-E8 +p +ws +-0 Backup song alloc info 17 +dE9 +bb +be +d-EE +p +ws +dEA +bb +be +d-ED +p +ws +dEB +bb +be +d-EC +p +ws +dEC +bb +be +d-EB +p +ws +dED +bb +be +d-EA +p +ws +-0 Backup song 18 +dEE +bb +be +d-F0 +p +ws +dEF +bb +be +d-EF +p +ws +-0 Backup song alloc info 18 +dF0 +bb +be +d-F5 +p +ws +dF1 +bb +be +d-F4 +p +ws +dF2 +bb +be +d-F3 +p +ws +dF3 +bb +be +d-F2 +p +ws +dF4 +bb +be +d-F1 +p +ws +-0 Backup song 19 +dF5 +bb +be +d-F7 +p +ws +dF6 +bb +be +d-F6 +p +ws +-0 Backup song alloc info 19 +dF7 +bb +be +d-FC +p +ws +dF8 +bb +be +d-FB +p +ws +dF9 +bb +be +d-FA +p +ws +dFA +bb +be +d-F9 +p +ws +dFB +bb +be +d-F8 +p +ws +-0 Backup song 20 +dFC +bb +be +d-FE +p +ws +dFD +bb +be +d-FD +p +ws +-0 Backup song alloc info 20 +dFE +bb +be +d-103 +p +ws +dFF +bb +be +d-102 +p +ws +d100 +bb +be +d-101 +p +ws +d101 +bb +be +d-100 +p +ws +d102 +bb +be +d-FF +p +ws +-0 Backup song 21 +d103 +bb +be +d-105 +p +ws +d104 +bb +be +d-104 +p +ws +-0 Backup song alloc info 21 +d105 +bb +be +d-10A +p +ws +d106 +bb +be +d-109 +p +ws +d107 +bb +be +d-108 +p +ws +d108 +bb +be +d-107 +p +ws +d109 +bb +be +d-106 +p +ws +-0 Backup song 22 +d10A +bb +be +d-10C +p +ws +d10B +bb +be +d-10B +p +ws +-0 Backup song alloc info 22 +d10C +bb +be +d-111 +p +ws +d10D +bb +be +d-110 +p +ws +d10E +bb +be +d-10F +p +ws +d10F +bb +be +d-10E +p +ws +d110 +bb +be +d-10D +p +ws +-0 Backup song 23 +d111 +bb +be +d-113 +p +ws +d112 +bb +be +d-112 +p +ws +-0 Backup song alloc info 23 +d113 +bb +be +d-118 +p +ws +d114 +bb +be +d-117 +p +ws +d115 +bb +be +d-116 +p +ws +d116 +bb +be +d-115 +p +ws +d117 +bb +be +d-114 +p +ws +-0 Backup song 24 +d118 +bb +be +d-11A +p +ws +d119 +bb +be +d-119 +p +ws +-0 Backup song alloc info 24 +d11A +bb +be +d-11F +p +ws +d11B +bb +be +d-11E +p +ws +d11C +bb +be +d-11D +p +ws +d11D +bb +be +d-11C +p +ws +d11E +bb +be +d-11B +p +ws +-0 Backup song 25 +d11F +bb +be +d-121 +p +ws +d120 +bb +be +d-120 +p +ws +-0 Backup song alloc info 25 +d121 +bb +be +d-126 +p +ws +d122 +bb +be +d-125 +p +ws +d123 +bb +be +d-124 +p +ws +d124 +bb +be +d-123 +p +ws +d125 +bb +be +d-122 +p +ws +-0 Backup song 26 +d126 +bb +be +d-128 +p +ws +d127 +bb +be +d-127 +p +ws +-0 Backup song alloc info 26 +d128 +bb +be +d-12D +p +ws +d129 +bb +be +d-12C +p +ws +d12A +bb +be +d-12B +p +ws +d12B +bb +be +d-12A +p +ws +d12C +bb +be +d-129 +p +ws +-0 Backup song 27 +d12D +bb +be +d-12F +p +ws +d12E +bb +be +d-12E +p +ws +-0 Backup song alloc info 27 +d12F +bb +be +d-134 +p +ws +d130 +bb +be +d-133 +p +ws +d131 +bb +be +d-132 +p +ws +d132 +bb +be +d-131 +p +ws +d133 +bb +be +d-130 +p +ws +-0 Backup song 28 +d134 +bb +be +d-136 +p +ws +d135 +bb +be +d-135 +p +ws +-0 Backup song alloc info 28 +d136 +bb +be +d-13B +p +ws +d137 +bb +be +d-13A +p +ws +d138 +bb +be +d-139 +p +ws +d139 +bb +be +d-138 +p +ws +d13A +bb +be +d-137 +p +ws +-0 Backup song 29 +d13B +bb +be +d-13D +p +ws +d13C +bb +be +d-13C +p +ws +-0 Backup song alloc info 29 +d13D +bb +be +d-142 +p +ws +d13E +bb +be +d-141 +p +ws +d13F +bb +be +d-140 +p +ws +d140 +bb +be +d-13F +p +ws +d141 +bb +be +d-13E +p +ws +-0 Backup song 30 +d142 +bb +be +d-144 +p +ws +d143 +bb +be +d-143 +p +ws +-0 Backup song alloc info 30 +d144 +bb +be +d-149 +p +ws +d145 +bb +be +d-148 +p +ws +d146 +bb +be +d-147 +p +ws +d147 +bb +be +d-146 +p +ws +d148 +bb +be +d-145 +p +ws +-0 Backup song 31 +d149 +bb +be +d-14B +p +ws +d14A +bb +be +d-14A +p +ws +-0 Backup song alloc info 31 +d14B +bb +be +d-150 +p +ws +d14C +bb +be +d-14F +p +ws +d14D +bb +be +d-14E +p +ws +d14E +bb +be +d-14D +p +ws +d14F +bb +be +d-14C +p +ws +-0 Backup song 32 +d150 +bb +be +d-152 +p +ws +d151 +bb +be +d-151 +p +ws +-0 Backup song alloc info 32 +d152 +bb +be +d-157 +p +ws +d153 +bb +be +d-156 +p +ws +d154 +bb +be +d-155 +p +ws +d155 +bb +be +d-154 +p +ws +d156 +bb +be +d-153 +p +ws +-0 Backup song 33 +d157 +bb +be +d-159 +p +ws +d158 +bb +be +d-158 +p +ws +-0 Backup song alloc info 33 +d159 +bb +be +d-15E +p +ws +d15A +bb +be +d-15D +p +ws +d15B +bb +be +d-15C +p +ws +d15C +bb +be +d-15B +p +ws +d15D +bb +be +d-15A +p +ws +-0 Backup song 34 +d15E +bb +be +d-160 +p +ws +d15F +bb +be +d-15F +p +ws +-0 Backup song alloc info 34 +d160 +bb +be +d-165 +p +ws +d161 +bb +be +d-164 +p +ws +d162 +bb +be +d-163 +p +ws +d163 +bb +be +d-162 +p +ws +d164 +bb +be +d-161 +p +ws +-0 Backup song 35 +d165 +bb +be +d-167 +p +ws +d166 +bb +be +d-166 +p +ws +-0 Backup song alloc info 35 +d167 +bb +be +d-16C +p +ws +d168 +bb +be +d-16B +p +ws +d169 +bb +be +d-16A +p +ws +d16A +bb +be +d-169 +p +ws +d16B +bb +be +d-168 +p +ws +-0 Backup song 36 +d16C +bb +be +d-16E +p +ws +d16D +bb +be +d-16D +p +ws +-0 Backup song alloc info 36 +d16E +bb +be +d-173 +p +ws +d16F +bb +be +d-172 +p +ws +d170 +bb +be +d-171 +p +ws +d171 +bb +be +d-170 +p +ws +d172 +bb +be +d-16F +p +ws +-0 Backup song 37 +d173 +bb +be +d-175 +p +ws +d174 +bb +be +d-174 +p +ws +-0 Backup song alloc info 37 +d175 +bb +be +d-17A +p +ws +d176 +bb +be +d-179 +p +ws +d177 +bb +be +d-178 +p +ws +d178 +bb +be +d-177 +p +ws +d179 +bb +be +d-176 +p +ws +-0 Backup song 38 +d17A +bb +be +d-17C +p +ws +d17B +bb +be +d-17B +p +ws +-0 Backup song alloc info 38 +d17C +bb +be +d-181 +p +ws +d17D +bb +be +d-180 +p +ws +d17E +bb +be +d-17F +p +ws +d17F +bb +be +d-17E +p +ws +d180 +bb +be +d-17D +p +ws +-0 Backup song 39 +d181 +bb +be +d-183 +p +ws +d182 +bb +be +d-182 +p +ws +-0 Backup song alloc info 39 +d183 +bb +be +d-188 +p +ws +d184 +bb +be +d-187 +p +ws +d185 +bb +be +d-186 +p +ws +d186 +bb +be +d-185 +p +ws +d187 +bb +be +d-184 +p +ws +-0 Backup song 40 +d188 +bb +be +d-18A +p +ws +d189 +bb +be +d-189 +p +ws +-0 Backup song alloc info 40 +d18A +bb +be +d-18F +p +ws +d18B +bb +be +d-18E +p +ws +d18C +bb +be +d-18D +p +ws +d18D +bb +be +d-18C +p +ws +d18E +bb +be +d-18B +p +ws +-0 Backup song 41 +d18F +bb +be +d-191 +p +ws +d190 +bb +be +d-190 +p +ws +-0 Backup song alloc info 41 +d191 +bb +be +d-196 +p +ws +d192 +bb +be +d-195 +p +ws +d193 +bb +be +d-194 +p +ws +d194 +bb +be +d-193 +p +ws +d195 +bb +be +d-192 +p +ws +-0 Backup song 42 +d196 +bb +be +d-198 +p +ws +d197 +bb +be +d-197 +p +ws +-0 Backup song alloc info 42 +d198 +bb +be +d-19D +p +ws +d199 +bb +be +d-19C +p +ws +d19A +bb +be +d-19B +p +ws +d19B +bb +be +d-19A +p +ws +d19C +bb +be +d-199 +p +ws +-0 Backup song 43 +d19D +bb +be +d-19F +p +ws +d19E +bb +be +d-19E +p +ws +-0 Backup song alloc info 43 +d19F +bb +be +d-1A4 +p +ws +d1A0 +bb +be +d-1A3 +p +ws +d1A1 +bb +be +d-1A2 +p +ws +d1A2 +bb +be +d-1A1 +p +ws +d1A3 +bb +be +d-1A0 +p +ws +-0 Backup song 44 +d1A4 +bb +be +d-1A6 +p +ws +d1A5 +bb +be +d-1A5 +p +ws +-0 Backup song alloc info 44 +d1A6 +bb +be +d-1AB +p +ws +d1A7 +bb +be +d-1AA +p +ws +d1A8 +bb +be +d-1A9 +p +ws +d1A9 +bb +be +d-1A8 +p +ws +d1AA +bb +be +d-1A7 +p +ws +-0 Backup song 45 +d1AB +bb +be +d-1AD +p +ws +d1AC +bb +be +d-1AC +p +ws +-0 Backup song alloc info 45 +d1AD +bb +be +d-1B2 +p +ws +d1AE +bb +be +d-1B1 +p +ws +d1AF +bb +be +d-1B0 +p +ws +d1B0 +bb +be +d-1AF +p +ws +d1B1 +bb +be +d-1AE +p +ws +-0 Backup song 46 +d1B2 +bb +be +d-1B4 +p +ws +d1B3 +bb +be +d-1B3 +p +ws +-0 Backup song alloc info 46 +d1B4 +bb +be +d-1B9 +p +ws +d1B5 +bb +be +d-1B8 +p +ws +d1B6 +bb +be +d-1B7 +p +ws +d1B7 +bb +be +d-1B6 +p +ws +d1B8 +bb +be +d-1B5 +p +ws +-0 Backup song 47 +d1B9 +bb +be +d-1BB +p +ws +d1BA +bb +be +d-1BA +p +ws +-0 Backup song alloc info 47 +d1BB +bb +be +d-1C0 +p +ws +d1BC +bb +be +d-1BF +p +ws +d1BD +bb +be +d-1BE +p +ws +d1BE +bb +be +d-1BD +p +ws +d1BF +bb +be +d-1BC +p +ws +-0 Backup song 48 +d1C0 +bb +be +d-1C2 +p +ws +d1C1 +bb +be +d-1C1 +p +ws +-0 Backup song alloc info 48 +d1C2 +bb +be +d-1C7 +p +ws +d1C3 +bb +be +d-1C6 +p +ws +d1C4 +bb +be +d-1C5 +p +ws +d1C5 +bb +be +d-1C4 +p +ws +d1C6 +bb +be +d-1C3 +p +ws +-0 Backup song 49 +d1C7 +bb +be +d-1C9 +p +ws +d1C8 +bb +be +d-1C8 +p +ws +-0 Backup song alloc info 49 +d1C9 +bb +be +d-1CE +p +ws +d1CA +bb +be +d-1CD +p +ws +d1CB +bb +be +d-1CC +p +ws +d1CC +bb +be +d-1CB +p +ws +d1CD +bb +be +d-1CA +p +ws +-0 Backup song 50 +d1CE +bb +be +d-1D0 +p +ws +d1CF +bb +be +d-1CF +p +ws +-0 Backup song alloc info 50 +d1D0 +bb +be +d-1D5 +p +ws +d1D1 +bb +be +d-1D4 +p +ws +d1D2 +bb +be +d-1D3 +p +ws +d1D3 +bb +be +d-1D2 +p +ws +d1D4 +bb +be +d-1D1 +p +ws +-0 Backup song 51 +d1D5 +bb +be +d-1D7 +p +ws +d1D6 +bb +be +d-1D6 +p +ws +-0 Backup song alloc info 51 +d1D7 +bb +be +d-1DC +p +ws +d1D8 +bb +be +d-1DB +p +ws +d1D9 +bb +be +d-1DA +p +ws +d1DA +bb +be +d-1D9 +p +ws +d1DB +bb +be +d-1D8 +p +ws +-0 Backup song 52 +d1DC +bb +be +d-1DE +p +ws +d1DD +bb +be +d-1DD +p +ws +-0 Backup song alloc info 52 +d1DE +bb +be +d-1E3 +p +ws +d1DF +bb +be +d-1E2 +p +ws +d1E0 +bb +be +d-1E1 +p +ws +d1E1 +bb +be +d-1E0 +p +ws +d1E2 +bb +be +d-1DF +p +ws +-0 Backup song 53 +d1E3 +bb +be +d-1E5 +p +ws +d1E4 +bb +be +d-1E4 +p +ws +-0 Backup song alloc info 53 +d1E5 +bb +be +d-1EA +p +ws +d1E6 +bb +be +d-1E9 +p +ws +d1E7 +bb +be +d-1E8 +p +ws +d1E8 +bb +be +d-1E7 +p +ws +d1E9 +bb +be +d-1E6 +p +ws +-0 Backup song 54 +d1EA +bb +be +d-1EC +p +ws +d1EB +bb +be +d-1EB +p +ws +-0 Backup song alloc info 54 +d1EC +bb +be +d-1F1 +p +ws +d1ED +bb +be +d-1F0 +p +ws +d1EE +bb +be +d-1EF +p +ws +d1EF +bb +be +d-1EE +p +ws +d1F0 +bb +be +d-1ED +p +ws +-0 Backup song 55 +d1F1 +bb +be +d-1F3 +p +ws +d1F2 +bb +be +d-1F2 +p +ws +-0 Backup song alloc info 55 +d1F3 +bb +be +d-1F8 +p +ws +d1F4 +bb +be +d-1F7 +p +ws +d1F5 +bb +be +d-1F6 +p +ws +d1F6 +bb +be +d-1F5 +p +ws +d1F7 +bb +be +d-1F4 +p +ws +-0 Backup song 56 +d1F8 +bb +be +d-1FA +p +ws +d1F9 +bb +be +d-1F9 +p +ws +-0 Backup song alloc info 56 +d1FA +bb +be +d-1FF +p +ws +d1FB +bb +be +d-1FE +p +ws +d1FC +bb +be +d-1FD +p +ws +d1FD +bb +be +d-1FC +p +ws +d1FE +bb +be +d-1FB +p +ws +-0 Backup song 57 +d1FF +bb +be +d-201 +p +ws +d200 +bb +be +d-200 +p +ws +-0 Backup song alloc info 57 +d201 +bb +be +d-206 +p +ws +d202 +bb +be +d-205 +p +ws +d203 +bb +be +d-204 +p +ws +d204 +bb +be +d-203 +p +ws +d205 +bb +be +d-202 +p +ws +-0 Backup song 58 +d206 +bb +be +d-208 +p +ws +d207 +bb +be +d-207 +p +ws +-0 Backup song alloc info 58 +d208 +bb +be +d-20D +p +ws +d209 +bb +be +d-20C +p +ws +d20A +bb +be +d-20B +p +ws +d20B +bb +be +d-20A +p +ws +d20C +bb +be +d-209 +p +ws +-0 Backup song 59 +d20D +bb +be +d-20F +p +ws +d20E +bb +be +d-20E +p +ws +-0 Backup song alloc info 59 +d20F +bb +be +d-214 +p +ws +d210 +bb +be +d-213 +p +ws +d211 +bb +be +d-212 +p +ws +d212 +bb +be +d-211 +p +ws +d213 +bb +be +d-210 +p +ws +-0 Backup song 60 +d214 +bb +be +d-216 +p +ws +d215 +bb +be +d-215 +p +ws +-0 Backup song alloc info 60 +d216 +bb +be +d-21B +p +ws +d217 +bb +be +d-21A +p +ws +d218 +bb +be +d-219 +p +ws +d219 +bb +be +d-218 +p +ws +d21A +bb +be +d-217 +p +ws +-0 Backup song 61 +d21B +bb +be +d-21D +p +ws +d21C +bb +be +d-21C +p +ws +-0 Backup song alloc info 61 +d21D +bb +be +d-222 +p +ws +d21E +bb +be +d-221 +p +ws +d21F +bb +be +d-220 +p +ws +d220 +bb +be +d-21F +p +ws +d221 +bb +be +d-21E +p +ws +-0 Backup song 62 +d222 +bb +be +d-224 +p +ws +d223 +bb +be +d-223 +p +ws +-0 Backup song alloc info 62 +d224 +bb +be +d-229 +p +ws +d225 +bb +be +d-228 +p +ws +d226 +bb +be +d-227 +p +ws +d227 +bb +be +d-226 +p +ws +d228 +bb +be +d-225 +p +ws +-0 Backup song 63 +d229 +bb +be +d-22B +p +ws +d22A +bb +be +d-22A +p +ws +-0 Backup song alloc info 63 +d22B +bb +be +d-230 +p +ws +d22C +bb +be +d-22F +p +ws +d22D +bb +be +d-22E +p +ws +d22E +bb +be +d-22D +p +ws +d22F +bb +be +d-22C +p +ws +-0 Backup song 64 +d230 +bb +be +d-232 +p +ws +d231 +bb +be +d-231 +p +ws +-0 Backup song alloc info 64 +d232 +bb +be +d-237 +p +ws +d233 +bb +be +d-236 +p +ws +d234 +bb +be +d-235 +p +ws +d235 +bb +be +d-234 +p +ws +d236 +bb +be +d-233 +p +ws +-0 Backup song 65 +d237 +bb +be +d-239 +p +ws +d238 +bb +be +d-238 +p +ws +-0 Backup song alloc info 65 +d239 +bb +be +d-23E +p +ws +d23A +bb +be +d-23D +p +ws +d23B +bb +be +d-23C +p +ws +d23C +bb +be +d-23B +p +ws +d23D +bb +be +d-23A +p +ws +-0 Backup song 66 +d23E +bb +be +d-240 +p +ws +d23F +bb +be +d-23F +p +ws +-0 Backup song alloc info 66 +d240 +bb +be +d-245 +p +ws +d241 +bb +be +d-244 +p +ws +d242 +bb +be +d-243 +p +ws +d243 +bb +be +d-242 +p +ws +d244 +bb +be +d-241 +p +ws +-0 Backup song 67 +d245 +bb +be +d-247 +p +ws +d246 +bb +be +d-246 +p +ws +-0 Backup song alloc info 67 +d247 +bb +be +d-24C +p +ws +d248 +bb +be +d-24B +p +ws +d249 +bb +be +d-24A +p +ws +d24A +bb +be +d-249 +p +ws +d24B +bb +be +d-248 +p +ws +-0 Backup song 68 +d24C +bb +be +d-24E +p +ws +d24D +bb +be +d-24D +p +ws +-0 Backup song alloc info 68 +d24E +bb +be +d-253 +p +ws +d24F +bb +be +d-252 +p +ws +d250 +bb +be +d-251 +p +ws +d251 +bb +be +d-250 +p +ws +d252 +bb +be +d-24F +p +ws +-0 Backup song 69 +d253 +bb +be +d-255 +p +ws +d254 +bb +be +d-254 +p +ws +-0 Backup song alloc info 69 +d255 +bb +be +d-25A +p +ws +d256 +bb +be +d-259 +p +ws +d257 +bb +be +d-258 +p +ws +d258 +bb +be +d-257 +p +ws +d259 +bb +be +d-256 +p +ws +-0 Backup song 70 +d25A +bb +be +d-25C +p +ws +d25B +bb +be +d-25B +p +ws +-0 Backup song alloc info 70 +d25C +bb +be +d-261 +p +ws +d25D +bb +be +d-260 +p +ws +d25E +bb +be +d-25F +p +ws +d25F +bb +be +d-25E +p +ws +d260 +bb +be +d-25D +p +ws +-0 Backup song 71 +d261 +bb +be +d-263 +p +ws +d262 +bb +be +d-262 +p +ws +-0 Backup song alloc info 71 +d263 +bb +be +d-268 +p +ws +d264 +bb +be +d-267 +p +ws +d265 +bb +be +d-266 +p +ws +d266 +bb +be +d-265 +p +ws +d267 +bb +be +d-264 +p +ws +-0 Backup song 72 +d268 +bb +be +d-26A +p +ws +d269 +bb +be +d-269 +p +ws +-0 Backup song alloc info 72 +d26A +bb +be +d-26F +p +ws +d26B +bb +be +d-26E +p +ws +d26C +bb +be +d-26D +p +ws +d26D +bb +be +d-26C +p +ws +d26E +bb +be +d-26B +p +ws +-0 Backup song 73 +d26F +bb +be +d-271 +p +ws +d270 +bb +be +d-270 +p +ws +-0 Backup song alloc info 73 +d271 +bb +be +d-276 +p +ws +d272 +bb +be +d-275 +p +ws +d273 +bb +be +d-274 +p +ws +d274 +bb +be +d-273 +p +ws +d275 +bb +be +d-272 +p +ws +-0 Backup song 74 +d276 +bb +be +d-278 +p +ws +d277 +bb +be +d-277 +p +ws +-0 Backup song alloc info 74 +d278 +bb +be +d-27D +p +ws +d279 +bb +be +d-27C +p +ws +d27A +bb +be +d-27B +p +ws +d27B +bb +be +d-27A +p +ws +d27C +bb +be +d-279 +p +ws +-0 Backup song 75 +d27D +bb +be +d-27F +p +ws +d27E +bb +be +d-27E +p +ws +-0 Backup song alloc info 75 +d27F +bb +be +d-284 +p +ws +d280 +bb +be +d-283 +p +ws +d281 +bb +be +d-282 +p +ws +d282 +bb +be +d-281 +p +ws +d283 +bb +be +d-280 +p +ws +-0 Backup song 76 +d284 +bb +be +d-286 +p +ws +d285 +bb +be +d-285 +p +ws +-0 Backup song alloc info 76 +d286 +bb +be +d-28B +p +ws +d287 +bb +be +d-28A +p +ws +d288 +bb +be +d-289 +p +ws +d289 +bb +be +d-288 +p +ws +d28A +bb +be +d-287 +p +ws +-0 Backup song 77 +d28B +bb +be +d-28D +p +ws +d28C +bb +be +d-28C +p +ws +-0 Backup song alloc info 77 +d28D +bb +be +d-292 +p +ws +d28E +bb +be +d-291 +p +ws +d28F +bb +be +d-290 +p +ws +d290 +bb +be +d-28F +p +ws +d291 +bb +be +d-28E +p +ws +-0 Backup song 78 +d292 +bb +be +d-294 +p +ws +d293 +bb +be +d-293 +p +ws +-0 Backup song alloc info 78 +d294 +bb +be +d-299 +p +ws +d295 +bb +be +d-298 +p +ws +d296 +bb +be +d-297 +p +ws +d297 +bb +be +d-296 +p +ws +d298 +bb +be +d-295 +p +ws +-0 Backup song 79 +d299 +bb +be +d-29B +p +ws +d29A +bb +be +d-29A +p +ws +-0 Backup song alloc info 79 +d29B +bb +be +d-2A0 +p +ws +d29C +bb +be +d-29F +p +ws +d29D +bb +be +d-29E +p +ws +d29E +bb +be +d-29D +p +ws +d29F +bb +be +d-29C +p +ws +-0 Backup song 80 +d2A0 +bb +be +d-2A2 +p +ws +d2A1 +bb +be +d-2A1 +p +ws +-0 Backup song alloc info 80 +d2A2 +bb +be +d-2A7 +p +ws +d2A3 +bb +be +d-2A6 +p +ws +d2A4 +bb +be +d-2A5 +p +ws +d2A5 +bb +be +d-2A4 +p +ws +d2A6 +bb +be +d-2A3 +p +ws +-0 Backup song 81 +d2A7 +bb +be +d-2A9 +p +ws +d2A8 +bb +be +d-2A8 +p +ws +-0 Backup song alloc info 81 +d2A9 +bb +be +d-2AE +p +ws +d2AA +bb +be +d-2AD +p +ws +d2AB +bb +be +d-2AC +p +ws +d2AC +bb +be +d-2AB +p +ws +d2AD +bb +be +d-2AA +p +ws +-0 Backup song 82 +d2AE +bb +be +d-2B0 +p +ws +d2AF +bb +be +d-2AF +p +ws +-0 Backup song alloc info 82 +d2B0 +bb +be +d-2B5 +p +ws +d2B1 +bb +be +d-2B4 +p +ws +d2B2 +bb +be +d-2B3 +p +ws +d2B3 +bb +be +d-2B2 +p +ws +d2B4 +bb +be +d-2B1 +p +ws +-0 Backup song 83 +d2B5 +bb +be +d-2B7 +p +ws +d2B6 +bb +be +d-2B6 +p +ws +-0 Backup song alloc info 83 +d2B7 +bb +be +d-2BC +p +ws +d2B8 +bb +be +d-2BB +p +ws +d2B9 +bb +be +d-2BA +p +ws +d2BA +bb +be +d-2B9 +p +ws +d2BB +bb +be +d-2B8 +p +ws +-0 Backup song 84 +d2BC +bb +be +d-2BE +p +ws +d2BD +bb +be +d-2BD +p +ws +-0 Backup song alloc info 84 +d2BE +bb +be +d-2C3 +p +ws +d2BF +bb +be +d-2C2 +p +ws +d2C0 +bb +be +d-2C1 +p +ws +d2C1 +bb +be +d-2C0 +p +ws +d2C2 +bb +be +d-2BF +p +ws +-0 Backup song 85 +d2C3 +bb +be +d-2C5 +p +ws +d2C4 +bb +be +d-2C4 +p +ws +-0 Backup song alloc info 85 +d2C5 +bb +be +d-2CA +p +ws +d2C6 +bb +be +d-2C9 +p +ws +d2C7 +bb +be +d-2C8 +p +ws +d2C8 +bb +be +d-2C7 +p +ws +d2C9 +bb +be +d-2C6 +p +ws +-0 Backup song 86 +d2CA +bb +be +d-2CC +p +ws +d2CB +bb +be +d-2CB +p +ws +-0 Backup song alloc info 86 +d2CC +bb +be +d-2D1 +p +ws +d2CD +bb +be +d-2D0 +p +ws +d2CE +bb +be +d-2CF +p +ws +d2CF +bb +be +d-2CE +p +ws +d2D0 +bb +be +d-2CD +p +ws +-0 Backup song 87 +d2D1 +bb +be +d-2D3 +p +ws +d2D2 +bb +be +d-2D2 +p +ws +-0 Backup song alloc info 87 +d2D3 +bb +be +d-2D8 +p +ws +d2D4 +bb +be +d-2D7 +p +ws +d2D5 +bb +be +d-2D6 +p +ws +d2D6 +bb +be +d-2D5 +p +ws +d2D7 +bb +be +d-2D4 +p +ws +-0 Backup song 88 +d2D8 +bb +be +d-2DA +p +ws +d2D9 +bb +be +d-2D9 +p +ws +-0 Backup song alloc info 88 +d2DA +bb +be +d-2DF +p +ws +d2DB +bb +be +d-2DE +p +ws +d2DC +bb +be +d-2DD +p +ws +d2DD +bb +be +d-2DC +p +ws +d2DE +bb +be +d-2DB +p +ws +-0 Backup song 89 +d2DF +bb +be +d-2E1 +p +ws +d2E0 +bb +be +d-2E0 +p +ws +-0 Backup song alloc info 89 +d2E1 +bb +be +d-2E6 +p +ws +d2E2 +bb +be +d-2E5 +p +ws +d2E3 +bb +be +d-2E4 +p +ws +d2E4 +bb +be +d-2E3 +p +ws +d2E5 +bb +be +d-2E2 +p +ws +-0 Backup song 90 +d2E6 +bb +be +d-2E8 +p +ws +d2E7 +bb +be +d-2E7 +p +ws +-0 Backup song alloc info 90 +d2E8 +bb +be +d-2ED +p +ws +d2E9 +bb +be +d-2EC +p +ws +d2EA +bb +be +d-2EB +p +ws +d2EB +bb +be +d-2EA +p +ws +d2EC +bb +be +d-2E9 +p +ws +-0 Backup song 91 +d2ED +bb +be +d-2EF +p +ws +d2EE +bb +be +d-2EE +p +ws +-0 Backup song alloc info 91 +d2EF +bb +be +d-2F4 +p +ws +d2F0 +bb +be +d-2F3 +p +ws +d2F1 +bb +be +d-2F2 +p +ws +d2F2 +bb +be +d-2F1 +p +ws +d2F3 +bb +be +d-2F0 +p +ws +-0 Backup song 92 +d2F4 +bb +be +d-2F6 +p +ws +d2F5 +bb +be +d-2F5 +p +ws +-0 Backup song alloc info 92 +d2F6 +bb +be +d-2FB +p +ws +d2F7 +bb +be +d-2FA +p +ws +d2F8 +bb +be +d-2F9 +p +ws +d2F9 +bb +be +d-2F8 +p +ws +d2FA +bb +be +d-2F7 +p +ws +-0 Backup song 93 +d2FB +bb +be +d-2FD +p +ws +d2FC +bb +be +d-2FC +p +ws +-0 Backup song alloc info 93 +d2FD +bb +be +d-302 +p +ws +d2FE +bb +be +d-301 +p +ws +d2FF +bb +be +d-300 +p +ws +d300 +bb +be +d-2FF +p +ws +d301 +bb +be +d-2FE +p +ws +-0 Backup song 94 +d302 +bb +be +d-304 +p +ws +d303 +bb +be +d-303 +p +ws +-0 Backup song alloc info 94 +d304 +bb +be +d-309 +p +ws +d305 +bb +be +d-308 +p +ws +d306 +bb +be +d-307 +p +ws +d307 +bb +be +d-306 +p +ws +d308 +bb +be +d-305 +p +ws +-0 Backup song 95 +d309 +bb +be +d-30B +p +ws +d30A +bb +be +d-30A +p +ws +-0 Backup song alloc info 95 +d30B +bb +be +d-310 +p +ws +d30C +bb +be +d-30F +p +ws +d30D +bb +be +d-30E +p +ws +d30E +bb +be +d-30D +p +ws +d30F +bb +be +d-30C +p +ws +-0 Backup song 96 +d310 +bb +be +d-312 +p +ws +d311 +bb +be +d-311 +p +ws +-0 Backup song alloc info 96 +d312 +bb +be +d-317 +p +ws +d313 +bb +be +d-316 +p +ws +d314 +bb +be +d-315 +p +ws +d315 +bb +be +d-314 +p +ws +d316 +bb +be +d-313 +p +ws +-0 Backup song 97 +d317 +bb +be +d-319 +p +ws +d318 +bb +be +d-318 +p +ws +-0 Backup song alloc info 97 +d319 +bb +be +d-31E +p +ws +d31A +bb +be +d-31D +p +ws +d31B +bb +be +d-31C +p +ws +d31C +bb +be +d-31B +p +ws +d31D +bb +be +d-31A +p +ws +-0 Backup song 98 +d31E +bb +be +d-320 +p +ws +d31F +bb +be +d-31F +p +ws +-0 Backup song alloc info 98 +d320 +bb +be +d-325 +p +ws +d321 +bb +be +d-324 +p +ws +d322 +bb +be +d-323 +p +ws +d323 +bb +be +d-322 +p +ws +d324 +bb +be +d-321 +p +ws +-0 Backup song 99 +d325 +bb +be +d-327 +p +ws +d326 +bb +be +d-326 +p +ws +-0 Backup song alloc info 99 +d327 +bb +be +d-32C +p +ws +d328 +bb +be +d-32B +p +ws +d329 +bb +be +d-32A +p +ws +d32A +bb +be +d-329 +p +ws +d32B +bb +be +d-328 +p +ws +q diff --git a/scripts/decodemtc b/scripts/decodemtc new file mode 100755 index 0000000..b190fb3 --- /dev/null +++ b/scripts/decodemtc @@ -0,0 +1,127 @@ +#!/usr/bin/perl -w -- +$|=1; # disable output buffering + +use strict; +use Switch; +use Time::HiRes qw(usleep ualarm gettimeofday tv_interval); +open (MTCSOURCE, "amidi --dump --port=hw:1,0,0|"); +my $set=0; +my $hour=0; +my $min=0; +my $sec=0; +my $frame=0; +my $tmptmphour=0; +my $tmptmpmin=0; +my $tmptmpsec=0; +my $tmptmpframe=0; +my $tmphour=0; +my $tmpmin=0; +my $tmpsec=0; +my $tmpframe=0; +my $qframe=-1; +my $settmp=0; +my $t0=[gettimeofday()]; +my $t1; +my $elapsed; +while () { + chomp($_); + if (/F0 7F (.*) 06 44 06 01 (.*) F7/) { + my @tc=split(' ',substr($_,21,14)); + $hour=hex("0x".$tc[0]) & 31; + $min=hex("0x".$tc[1]); + $sec=hex("0x".$tc[2]); + $frame=hex("0x".$tc[3]); + $qframe=hex("0x".$tc[4]); + printf "%02d:%02d:%02d.%02d/%02d (LOCATE) \r",$hour,$min,$sec,$frame,$qframe; + next; + } + if (/F1 (.*)/) { + $t1=[gettimeofday()]; + $elapsed=tv_interval($t0,$t1); + if ($elapsed>.1) { + $set=0; + $tmptmphour=0; + $tmptmpmin=0; + $tmptmpsec=0; + $tmptmpframe=0; + $settmp=0; + $qframe=-1; + $tmphour=0; + $tmpmin=0; + $tmpsec=0; + $tmpframe=0; + $hour=0; + $min=0; + $sec=0; + $frame=0; + + } + $t0=$t1; +# print $_." | "; + my $nibble=hex ("0x".substr($1,1,1)); + my $cmd=substr($1,0,1); + if ($set ==0) { + if ($cmd ne "0") { + print "skip\n"; + next; + } + } + $settmp=0; + switch (0+substr($1,0,1)) { + case 0 { + $tmptmpframe=($tmptmpframe & 0xf0)|$nibble; + $set|=1; + } + case 1 { + $tmptmpframe=($tmptmpframe & 0x0f)|($nibble*16); + $set|=2; + $tmpframe=$tmptmpframe; + $settmp=1; + } + case 2 { + $set|=4; + $tmptmpsec=($tmptmpsec & 0xf0)|$nibble; + } + case 3 { + $set|=8; + $tmptmpsec=($tmptmpsec & 0x0f)|($nibble*16); + } + $tmpsec=$tmptmpsec; + case 4 { + $set|=16; + $tmptmpmin=($tmptmpmin & 0xf0)|$nibble; + } + case 5 { + $set|=32; + $tmptmpmin=($tmptmpmin & 0x0f)|($nibble*16); + $tmpmin=$tmptmpmin; + } + case 6 { + $set|=64; + $tmptmphour=($tmptmphour & 0xf0)|$nibble; + } + case 7 { + $set|=128; + $tmptmphour=($tmptmphour & 0x0f)|(($nibble*16)&1); + $tmphour=$tmptmphour; + } + } + $qframe++; + if ($qframe > 3) { + $qframe=0; + if ($settmp == 0) { + $tmpframe++; + } + $frame=$tmpframe; + $sec=$tmpsec; + $min=$tmpmin; + $hour=$tmphour; + } + if ($set==255) { + printf "%02d:%02d:%02d.%02d/%02d \r",$hour,$min,$sec,$frame,$qframe; + } else { + printf "%02d:%02d:%02d.%02d/%02d (no lock)\r",$hour,$min,$sec,$frame,$qframe; + } + } +} +close (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 @@ +#!/usr/bin/perl -- +# +#http://en.wikipedia.org/wiki/SMPTE_time_code +sub bitnum { + my ($val,$bit)=@_; + while (1==1) { + if ($bit<=0) { + return $val % 2; + } + $val=int($val/2); + $bit--; + } +} +my $lastframe=-1; +my @smpteword; + +my $prevbitnum=-1; +my $prevhalfbit=-1; +my $prevoutval=0; +sub smpte_modulate { + my ($currbitval,$bitnum,$halfbit)=@_; + if (($bitnum!=$prevbitnum) || (($halfbit!=$prevhalfbit) && ($currbitval==1))) + { + $prevoutval=1-$prevoutval; + } + $prevbitnum=$bitnum; + $prevhalfbit=$halfbit; + return $prevoutval; +} + +sub smpte_timecodebit { + my ($insamplerate,$framerate,$nondrop,$insamnum)=@_; + my $samnum=$insamnum; + my $samplerate=$insamplerate; + if ($insamplerate!=48000) + { + $samplerate=48000; + $samnum=$insamnum*(48000/$insamplerate); + } + my $sampleinsecond=$samnum % $samplerate; + my $currentsecond=($samnum-$sampleinsecond)/$samplerate; + my $currenthour=int($currentsecond/3600); + $currentsecond-=3600*$currenthour; + my $currentminute=int($currentsecond/60); + $currentsecond-=60*$currentminute; + my $bitsperframe=80; + my $bitspersecond=$bitsperframe*$framerate; + my $samplesperbit=$samplerate/$bitspersecond; + my $samplesperframe=$samplerate/$framerate; + my $currentframe=int($sampleinsecond/$samplesperframe); + my $sampleinframe=$sampleinsecond-($currentframe*$samplesperframe); + my $bitinframe=int($sampleinframe/$samplesperbit); + my $subbit=int($sampleinframe-($bitinframe*$samplesperbit)); + my $halfbit=($samplesperbit/2); + + my $frameunits=($currentframe%10); + my $frametens=int(($currentframe-$frameunits)/10); + + my $secondsunits=($currentsecond%10); + my $secondstems=int(($currentsecond-$secondunits)/10); + + my $minuteunits=($currentminute%10); + my $minutetens=int(($currentminute-$minuteunits)/10); + + my $hourunits=($currenthour%10); + my $hourtens=int(($currenthour-$hourunits)/10); + + $smpteword[0]=bitnum($frameunits,0); + $smpteword[1]=bitnum($frameunits,1); + $smpteword[2]=bitnum($frameunits,2); + $smpteword[3]=bitnum($frameunits,3); + $smpteword[4]=0; + $smpteword[5]=0; + $smpteword[6]=0; + $smpteword[7]=0; + $smpteword[8]=bitnum($frametens,0); + $smpteword[9]=bitnum($frametens,1); + $smpteword[10]=0; + $smpteword[11]=0; + $smpteword[12]=0; + $smpteword[13]=0; + $smpteword[14]=0; + $smpteword[15]=0; + $smpteword[16]=bitnum($secondsunits,0); + $smpteword[17]=bitnum($secondsunits,1); + $smpteword[18]=bitnum($secondsunits,2); + $smpteword[19]=bitnum($secondsunits,3); + $smpteword[20]=0; + $smpteword[21]=0; + $smpteword[22]=0; + $smpteword[23]=0; + $smpteword[24]=bitnum($secondstens,0); + $smpteword[25]=bitnum($secondstens,1); + $smpteword[26]=bitnum($secondstens,2); + $smpteword[27]=0; #biphasemark, fill in later + $smpteword[28]=0; + $smpteword[29]=0; + $smpteword[30]=0; + $smpteword[31]=0; + $smpteword[32]=bitnum($minuteunits,0); + $smpteword[33]=bitnum($minuteunits,1); + $smpteword[34]=bitnum($minuteunits,2); + $smpteword[35]=bitnum($minuteunits,3); + $smpteword[36]=0; + $smpteword[37]=0; + $smpteword[38]=0; + $smpteword[39]=0; + $smpteword[40]=bitnum($minutetens,0); + $smpteword[41]=bitnum($minutetens,1); + $smpteword[42]=bitnum($minutetens,2); + $smpteword[43]=0; # binary group flag bit + $smpteword[44]=0; + $smpteword[45]=0; + $smpteword[46]=0; + $smpteword[47]=0; + $smpteword[48]=bitnum($hourunits,0); + $smpteword[49]=bitnum($hourunits,1); + $smpteword[50]=bitnum($hourunits,2); + $smpteword[51]=bitnum($hourunits,3); + $smpteword[52]=0; + $smpteword[53]=0; + $smpteword[54]=0; + $smpteword[55]=0; + $smpteword[56]=bitnum($hourtens,0); + $smpteword[57]=bitnum($hourtens,1); + $smpteword[58]=0; # reserved, must be 0 + $smpteword[59]=0; # binary group flag bit + $smpteword[60]=0; + $smpteword[61]=0; + $smpteword[62]=0; + $smpteword[63]=0; + + # sync word follows + $smpteword[64]=0; + $smpteword[65]=0; + $smpteword[66]=1; + $smpteword[67]=1; + $smpteword[68]=1; + $smpteword[69]=1; + $smpteword[70]=1; + $smpteword[71]=1; + $smpteword[72]=1; + $smpteword[73]=1; + $smpteword[74]=1; + $smpteword[75]=1; + $smpteword[76]=1; + $smpteword[77]=1; + $smpteword[78]=0; + $smpteword[79]=1; + my $parity=0; + for ($i=0;$i<=79;$i++) { + $parity+=$smpteword[$i]; + } + $smpteword[27]=$parity & 1; + + return $smpteword[$bitinframe]; + # Enable this to also perform bit modulation: + # ########################### + if ($subbit<$halfbit) { + return smpte_modulate($smpteword[$bitinframe],$bitinframe,0); + } + return smpte_modulate($smpteword[$bitinframe],$bitinframe,1); + ################################## + # or only use this to return the raw SMPTE bits. +} + +my $i; +my $samplerate=48000; +my $framerate=30; +$startsam=0; #($samplerate/$framerate); +my $nondrop=true; +for ($samnum=$startsam;$samnum<1500000;$samnum+=10) { + $x=smpte_timecodebit($samplerate,$framerate,$nondrop,$samnum); + if ($x==0) { + print "0"; #chr(0); + } else { + print "1"; #chr(255); + } + +} + 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 @@ +#!/usr/bin/perl -- + +sub dec2hex { + # parameter passed to + # the subfunction + my $decnum = $_[0]; + if ($decnum==0) { + return "0"; + } + # the final hex number + my $hexnum; + my $tempval; + while ($decnum != 0) { + # get the remainder (modulus function) + # by dividing by 16 + $tempval = $decnum % 16; + # convert to the appropriate letter + # if the value is greater than 9 + if ($tempval > 9) { + $tempval = chr($tempval + 55); + } + # 'concatenate' the number to + # what we have so far in what will + # be the final variable + $hexnum = $tempval . $hexnum ; + # new actually divide by 16, and + # keep the integer value of the + # answer + $decnum = int($decnum / 16); + # if we cant divide by 16, this is the + # last step + if ($decnum < 16) { + # convert to letters again.. + if ($decnum > 9) { + $decnum = chr($decnum + 55); + } + + # add this onto the final answer.. + # reset decnum variable to zero so loop + # will exit + $hexnum = $decnum . $hexnum; + $decnum = 0 + } + } + return $hexnum; +} # end sub + +sub writebackupblock ($$$$) { +my $i; + my $sector=shift; + my $blocksize=shift; + my $currentcount=shift; + my $remark=shift; + print "-0 ".$remark." ".$currentcount."\n"; + for ($i=1;$i<=$blocksize;$i++) { + print "d".dec2hex($sector+$i-1)."\n"; + print "bb\nbe\n"; + print "d-".dec2hex($sector+1+$blocksize-$i)."\n"; + print "p\nws\n"; + } +} +$sector=0; +$blocksize=1; +$count=1; +writebackupblock($sector,$blocksize,$count,"Backup superblock"); + +$sector+=$blocksize*$count; +$blocksize=1; +$count=1; +writebackupblock ($sector,$blocksize,$count,"Backup Drive info"); + +$sector+=$blocksize*$count; +$blocksize=3; +$count=1; +writebackupblock ($sector,$blocksize,$count,"Backup undo (?) usage"); + +$sector+=$blocksize*$count; +$blocksize=15; +$count=1; +writebackupblock ($sector,$blocksize,$count,"Backup drive usage table"); + +$sector+=$blocksize*$count; +$blocksize=1; +$count=99; +for ($i=1;$i<=$count;$i++) { + writebackupblock ($sector+$i-1,$blocksize,$i,"Backup project "); +} + +$sector+=$blocksize*$count; +$count=99; +for ($i=1;$i<=$count;$i++) { + $blocksize=2; + writebackupblock ($sector+(7*($i-1)),$blocksize,$i,"Backup song "); + $blocksize=5; + writebackupblock ($sector+(7*($i-1))+2,$blocksize,$i,"Backup song alloc info "); +} +print "q\n"; + diff --git a/scripts/hd24arm1 b/scripts/hd24arm1 new file mode 100755 index 0000000..6df5cca --- /dev/null +++ b/scripts/hd24arm1 @@ -0,0 +1,2 @@ +#!/bin/sh +amidi --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 @@ +#!/bin/sh +amidi --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 @@ +#!/bin/sh +amidi --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 @@ +#!/bin/sh +amidi --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 @@ +#!/bin/sh +amidi --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 @@ +#!/bin/sh +amidi --send-hex="f0 7f 7f 06 01 f7" + diff --git a/scripts/hd24mute1 b/scripts/hd24mute1 new file mode 100755 index 0000000..516f1e3 --- /dev/null +++ b/scripts/hd24mute1 @@ -0,0 +1,2 @@ +#!/bin/sh +amidi --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 @@ +#!/bin/sh +amidi --send-hex="f0 7f 7f 06 02 f7" + diff --git a/scripts/hd24stop b/scripts/hd24stop new file mode 100755 index 0000000..c34af04 --- /dev/null +++ b/scripts/hd24stop @@ -0,0 +1,3 @@ +#!/bin/sh +amidi --send-hex="f0 7f 7f 06 01 f7" + diff --git a/scripts/hd24unarmall b/scripts/hd24unarmall new file mode 100755 index 0000000..532c276 --- /dev/null +++ b/scripts/hd24unarmall @@ -0,0 +1,2 @@ +#!/bin/sh +amidi --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 @@ +// +// Programmer: Craig Stuart Sapp +// Creation Date: Tue Dec 22 20:12:18 PST 1998 +// Last Modified: Tue Dec 22 20:12:23 PST 1998 +// Filename: insimple.c +// Syntax: C; pthread +// $Smake: gcc -O3 -Wall -o %b %f -static -lpthread && strip %b +// + +#include +#include +#include +#include + +#define MIDI_DEVICE "/dev/sequencer" + + +int main(void) { + unsigned char inpacket[4]; + + // first open the sequencer device for reading. + int seqfd = open(MIDI_DEVICE, O_RDONLY); + if (seqfd == -1) { + printf("Error: cannot open %s\n", MIDI_DEVICE); + exit(1); + } + + // now just wait around for MIDI bytes to arrive and print them to screen. + while (1) { + read(seqfd, &inpacket, sizeof(inpacket)); + + // print the MIDI byte if this input packet contains one + if (inpacket[0] == SEQ_MIDIPUTC) { + printf("received MIDI byte: %d\n", inpacket[1]); + } + } + + return 0; +} + diff --git a/scripts/mtcspeak b/scripts/mtcspeak new file mode 100755 index 0000000..6ea6c27 --- /dev/null +++ b/scripts/mtcspeak @@ -0,0 +1,34 @@ +#!/usr/bin/perl -w -- +$|=1; # disable output buffering +use strict; +open (MTCSOURCE, "amidi --dump --port=hw:1,0,0|"); +open (STDOUT, "|espeak"); +my $hour=0; +my $min=0; +my $sec=0; +my $frame=0; +my $qframe=-1; +my $roundedframe; +while () { + chomp($_); + if (/F0 7F (.*) 06 44 06 01 (.*) F7/) { + my @tc=split(' ',substr($_,21,17)); + $hour=hex("0x".$tc[0]) & 31; + $min=hex("0x".$tc[1]); + $sec=hex("0x".$tc[2]); + $frame=hex("0x".$tc[3]); + $qframe=hex("0x".$tc[4]); + $roundedframe=$frame; + if ($qframe>=50) { + $roundedframe++; + } + if ($hour>0) { + print "$hour hours $min minutes $sec seconds $roundedframe frames\r\n"; + } + else + { + print "$min minutes $sec seconds $roundedframe frames\r\n"; + } + } +} +close (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 @@ +#!/usr/bin/perl -- +# Given an offset of a byte number on disk, +# this little script converts the given offset to the sector number +# where the audio starts that is allocated by the given byte in the +# usage table. +# It is assumed that the drive usage table starts on offset 0xa00 +# (sector 5). +# The blocks per cluster must be looked up in the boot record of the +# drive before using this script; it varies based on drive capacity. +my $blockspercluster=5; +my $sectorsperblock=0x480; +my $firstaudiosec=0x1397f6; +my $usagetablestart=0xa00; +my $recordingoffset=hex($ARGV[0]); +my $bitsperbyte=8; +my $startcluster=$recordingoffset-$usagetablestart; +my $audiosec=$firstaudiosec+($sectorsperblock*$blockspercluster*$bitsperbyte*$startcluster); + +print 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 @@ +#!/usr/bin/perl -- +# Given an audio sector number (based on alloc info of a song), +# this script converts that sector number to the byte offset on +# the drive where that sector number should be allocated. +# This is useful in combination with hd24hexview. +# Blocks per cluster must be looked up in the superblock of the drive; +# it varies depending on drive capacity. +my $blockspercluster=5; +my $sectorsperblock=0x480; +my $firstaudiosec=0x1397f6; +my $usagetablestart=0xa00; +my $audiosec=hex($ARGV[0]); +my $bitsperbyte=8; + +my $offs=($audiosec-$firstaudiosec)/0x480/$blockspercluster/$bitsperbyte+$usagetablestart; + +print 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 @@ +#!/usr/bin/perl -w -- +$|=1; # disable output buffering +use strict; +open (MTCSOURCE, "amidi --dump --port=hw:1,0,0|"); +my $hour=0; +my $min=0; +my $sec=0; +my $frame=0; +my $qframe=-1; +while () { + chomp($_); + if (/F0 7F (.*) 06 44 06 01 (.*) F7/) { + print $_; + my @tc=split(' ',substr($_,21,17)); + $hour=hex("0x".$tc[0]) & 31; + $min=hex("0x".$tc[1]); + $sec=hex("0x".$tc[2]); + $frame=hex("0x".$tc[3]); + $qframe=hex("0x".$tc[4]); + $roundedframe=$frame; + if ($qframe>=50) { + $roundedframe++; + } + if ($hour>0) { + print "$hour hours $min minutes $sec seconds $roundedframe\r\n"; + } + else + { + print "$min minutes $sec seconds $roundedframe\r\n"; + } + } +} +close (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 @@ +#!/usr/bin/perl -- +# sl2o -> converts Sectornumber and Length to Offset +# Given a sector number and block count (as mentioned in an allocation +# entry of a song), this little script tries to calculate which +# range of byte offsets on the drive correspond with the usage +# info of that allocation entry. This is useful in combination with +# hd24hexview. +# Blocks per cluster must be configured depending on the drive capacity. +# Look up the correct number in the superblock of the drive. +use POSIX floor; +my $sectorsperblock=0x480; +my $firstaudiosec=0x1397f6; +my $usagetablestart=0xa00; +my $blockspercluster=5; +my $bitsperbyte=8; +my $audiosec=hex($ARGV[0]); +my $seclen=floor(hex($ARGV[1])/($blockspercluster*$bitsperbyte)); + + +my $offs=($audiosec-$firstaudiosec)/0x480/$blockspercluster/$bitsperbyte+$usagetablestart; + +print sprintf("%x",$offs)."-"; +print 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 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0105 +header_name {.h} +code_name {.cc} +decl {//Copyright (c) 2003-2005 Nasca Octavian Paul} {} + +decl {//License: GNU GPL version 2 or later} {} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +class WidgetPDial {: {public Fl_Dial} +} { + Function {WidgetPDial(int x,int y, int w, int h, const char *label=0):Fl_Dial(x,y,w,h,label)} {} { + code {oldvalue=0.0;} {} + } + Function {handle(int event)} {return_type int + } { + code {double dragsize,v,min=minimum(),max=maximum(); +int my; + +switch (event){ +case FL_PUSH:oldvalue=value(); +case FL_DRAG: + my=-(Fl::event_y()-y()-h()/2); + + dragsize=200.0; + if (Fl::event_state(FL_BUTTON1)==0) dragsize*=10; + v=oldvalue+my/dragsize*(max-min); + if (vmax) v=max; + + //printf("%d %g %g\\n",my,v,oldvalue); + value(v); + value_damage(); + if (this->when()!=0) do_callback(); + return(1); + break; +case FL_RELEASE: + if (this->when()==0) do_callback(); + return(1); + break; +}; +return(0);} {selected + } + } + Function {drawgradient(int cx,int cy,int sx,double m1,double m2)} {return_type void + } { + code {for (int i=(int)(m1*sx);i<(int)(m2*sx);i++){ + double tmp=1.0-pow(i*1.0/sx,2.0); + pdialcolor(140+(int) (tmp*90),140+(int)(tmp*90),140+(int) (tmp*100)); + fl_arc(cx+sx/2-i/2,cy+sx/2-i/2,i,i,0,360); +};} {} + } + Function {draw()} {} { + code {int cx=x(),cy=y(),sx=w(),sy=h(); + + +//clears the button face +pdialcolor(190,190,200); +fl_pie(cx-1,cy-1,sx+2,sy+2,0,360); + +//Draws the button face (gradinet) +drawgradient(cx,cy,sx,0.5,1.0); + +double val=(value()-minimum())/(maximum()-minimum()); + +//draws the scale +pdialcolor(220,220,250); +double a1=angle1(),a2=angle2(); +for (int i=0;i<12;i++){ + double a=-i/12.0*360.0-val*(a2-a1)-a1; + fl_pie(cx,cy,sx,sy,a+270-3,a+3+270); +}; + +drawgradient(cx,cy,sx,0.0,0.75); + +//draws the value +double a=-(a2-a1)*val-a1; + + + + + +//draws the max and min points +pdialcolor(0,100,200); +int xp=(int)(cx+sx/2.0+sx/2.0*sin(angle1()/180.0*3.141592)); +int yp=(int)(cy+sy/2.0+sy/2.0*cos(angle1()/180.0*3.141592)); +fl_pie(xp-2,yp-2,4,4,0,360); + +xp=(int)(cx+sx/2.0+sx/2.0*sin(angle2()/180.0*3.141592)); +yp=(int)(cy+sy/2.0+sy/2.0*cos(angle2()/180.0*3.141592)); +fl_pie(xp-2,yp-2,4,4,0,360); + + + + + +fl_push_matrix(); + + fl_translate(cx+sx/2,cy+sy/2); + fl_rotate(a-90.0); + + fl_translate(sx/2,0); + + + fl_begin_polygon(); + pdialcolor(0,0,0); + fl_vertex(-10,-4); + fl_vertex(-10,4); + fl_vertex(0,0); + fl_end_polygon(); + + +fl_pop_matrix();} {} + } + Function {pdialcolor(int r,int g,int b)} {} { + code {if (active_r()) fl_color(r,g,b); + else fl_color(160-(160-r)/3,160-(160-b)/3,160-(160-b)/3);} {} + } + decl {double oldvalue;} {} +} 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 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0109 +header_name {.h} +code_name {.cxx} +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +class dialog_choosedevice {open +} { + decl {int buttonclicked;} {public + } + decl {int choice_startloc;} {public + } + decl {hd24fs* currfs;} {public + } + decl {int devnums[10000];} {} + decl {string* devicename;} {public + } + Function {fill_devices()} {open return_type void + } { + code {hd24devicenamegenerator* dng=new hd24devicenamegenerator(); + +__uint32 totnames=dng->getnumberofnames(); +device->add("--Use other device--",0,NULL,(void*)this); +int n=0; +for (__uint32 i=0;igetdevicename(i); + if (currfs->isexistingdevice(devname)) + { + device->add(devname->c_str(),0,NULL,(void*)this); + n++; + devnums[n]=i; + } + delete(devname); +} +device->value(1);} {} + } + Function {make_window(hd24fs* p_currfs)} {open + } { + Fl_Window {} { + label {Choose HD24 device} open selected + xywh {389 296 590 115} type Double color 52 labelsize 12 + code0 {buttonclicked=0;} + code1 {currfs=p_currfs;} + code2 {currdev->value(currfs->getdevicename()->c_str());} modal visible + } { + Fl_Button button_ok { + label OK + callback {buttonclicked=1; //OK +if (device->value()==0) { + devicename=new string(otherdevice->value()); +} else { + hd24devicenamegenerator* dng=new hd24devicenamegenerator(); + devicename=dng->getdevicename((__uint32)devnums[device->value()]); + delete dng; +} +//choice_startloc=fromloc->value(); +//choice_endloc=toloc->value(); +Fl_Window * x = Fl::first_window(); +x->~Fl_Window();} + xywh {430 85 70 25} + } + Fl_Button button_cancel { + label Cancel + callback {buttonclicked=2; //Cancel +Fl_Window * x = Fl::first_window(); +x->~Fl_Window();} + xywh {505 85 70 25} + } + Fl_Choice device { + label {Choose device:} + callback {if (device->value()!=0) { + otherdevice->deactivate(); +} else { + otherdevice->activate(); + otherdevice->take_focus(); +}} open + xywh {115 30 460 20} down_box BORDER_BOX labelsize 12 textsize 12 + code0 {fill_devices();} + } {} + Fl_Input otherdevice { + label {Other device:} + xywh {115 55 460 20} labelsize 12 textsize 12 deactivate + code0 {o->maximum_size(64);} + } + Fl_Output currdev { + label {Current device:} + xywh {115 5 240 20} box FLAT_BOX color 53 labelsize 12 textsize 12 + } + } + } +} 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 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0107 +header_name {.h} +code_name {.cxx} +decl {\#include } {public +} + +decl {\#include } {public +} + +class dialog_filesize {open +} { + decl {int buttonclicked;} {public + } + decl {__uint32 lastsector;} {public + } + Function {make_window()} {open + } { + Fl_Window filesizewindow { + label {Image size} open + xywh {351 357 340 105} type Double color 52 labelsize 12 + code0 {buttonclicked=0;} modal visible + } { + Fl_Button button_ok { + label OK + callback {buttonclicked=1; //OK +//char dest[66]; +//strncpy(&dest[0],currname->value(),64); +//dest[64]='\\0'; +//itemname=new string(dest); +__uint64 sizeval=strtol(filesize->value(),0,10); +switch (sizeunit->value()) { + case 0: + sizeval*=2048; + break; + case 1: + sizeval*=1024*2048; + break; + default: + break; +} +sizeval--; +if (sizeval>0xFFFFFFFF) { + sizeval=0xFFFFFFFF; +} +this->lastsector=(__uint32)(sizeval & 0xFFFFFFFF); +Fl_Window * x = Fl::first_window(); +x->~Fl_Window();} + xywh {185 80 70 20} labelsize 12 + } + Fl_Button button_cancel { + label Cancel + callback {buttonclicked=2; //Cancel +Fl_Window * x = Fl::first_window(); +x->~Fl_Window();} + xywh {260 80 70 20} labelsize 12 + } + Fl_Input filesize { + label {Enter size:} + xywh {120 55 120 20} labelsize 12 textsize 12 + code0 {o->maximum_size(16);} + code1 {o->take_focus();} + } + Fl_Choice preset { + label {Select preset size} open selected + xywh {120 10 210 20} down_box BORDER_BOX labelsize 12 textsize 12 + code0 {o->value(0);} + } { + MenuItem {} { + label {Specified below} + callback {sizeunit->activate(); +filesize->activate();} + xywh {0 0 34 21} labelsize 12 + } + MenuItem {} { + label {DVD+R (Single layer)} + callback {sizeunit->value(2); +filesize->value("9180416"); +sizeunit->deactivate(); +filesize->deactivate();} + xywh {10 10 34 21} labelsize 12 + } + MenuItem {} { + label {DVD-R (Single layer)} + callback {sizeunit->value(2); +filesize->value("9193984"); +sizeunit->deactivate(); +filesize->deactivate();} + xywh {20 20 34 21} labelsize 12 + } + MenuItem {} { + label {DVD+R (Dual Layer)} + callback {sizeunit->value(2); +filesize->value("16695296"); +sizeunit->deactivate(); +filesize->deactivate();} + xywh {20 20 34 21} labelsize 12 + } + MenuItem {} { + label {DVD-R (Dual layer)} + callback {sizeunit->value(2); +filesize->value("16686848"); +sizeunit->deactivate(); +filesize->deactivate();} + xywh {30 30 34 21} labelsize 12 + } + } + Fl_Choice sizeunit {open + xywh {245 55 85 20} down_box BORDER_BOX labelsize 12 + code0 {o->value(1);} + } { + MenuItem {} { + label MB + xywh {10 10 34 21} + } + MenuItem {} { + label GB + xywh {20 20 34 21} + } + MenuItem {} { + label Sectors + xywh {20 20 34 21} + } + } + Fl_Box {} { + label {- OR -} + xywh {85 33 35 17} labelsize 12 + } + } + } +} 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 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0107 +header_name {.h} +code_name {.cxx} +decl {\#include } {public +} + +class dialog_fromto {open +} { + decl {int buttonclicked;} {public + } + decl {int choice_startloc;} {public + } + decl {int choice_endloc;} {public + } + Function {make_window(hd24song* currsong)} {open + } { + Fl_Window {} { + label {Set range} open selected + xywh {315 299 360 85} type Double color 52 + code0 {buttonclicked=0;} + code1 {currsong=currsong;} modal visible + } { + Fl_Button button_ok { + label OK + callback {buttonclicked=1; //OK +choice_startloc=fromloc->value(); +choice_endloc=toloc->value(); +Fl_Window * x = Fl::first_window(); +x->~Fl_Window();} + xywh {210 55 70 25} + } + Fl_Button button_cancel { + label Cancel + callback {buttonclicked=2; //Cancel +Fl_Window * x = Fl::first_window(); +x->~Fl_Window();} + xywh {285 55 70 25} + } + Fl_Choice fromloc { + label {From location:} open + xywh {115 5 240 20} down_box BORDER_BOX labelsize 12 textsize 12 + } {} + Fl_Choice toloc { + label {To location:} open + xywh {115 30 240 20} down_box BORDER_BOX labelsize 12 textsize 12 + } {} + } + } +} 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 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0107 +header_name {.h} +code_name {.cxx} +decl {\#include } {public +} + +decl {\#include } {public +} + +class dialog_newproject {open +} { + decl {int buttonclicked;} {public + } + decl {char projectname[65];} {public + } + Function {make_window()} {open + } { + Fl_Window {} { + label {New project} open + xywh {247 417 500 85} type Double color 52 + code0 {buttonclicked=0;} modal visible + } { + Fl_Button button_ok { + label OK + callback { +for (int i=0;i<65;i++) { + projectname[i]=0; +} +strncpy(projectname,currname->value(),64); +buttonclicked=1; //OK +Fl_Window * x = Fl::first_window(); +x->~Fl_Window();} selected + xywh {345 60 70 20} labelsize 12 + } + Fl_Button button_cancel { + label Cancel + callback {buttonclicked=2; //Cancel +Fl_Window * x = Fl::first_window(); +x->~Fl_Window();} + xywh {420 60 70 20} labelsize 12 + } + Fl_Input currname { + label {Project name:} + callback {char filteredname[65]; +int x=strlen(o->value()); +if (x>64) { x=64; } +int src=0; +int filtered=0; +for (int i=0;ivalue()[i]=='\\\\') + || (o->value()[i]=='/') + || (o->value()[i]==':') + || (o->value()[i]=='*') + || (o->value()[i]=='?') + || (o->value()[i]=='"') + || (o->value()[i]=='<') + || (o->value()[i]=='>') + || (o->value()[i]=='\\\\') + || (o->value()[i]=='|')) + { + filtered=1; + continue; + } + filteredname[src]=o->value()[i]; + src++; +} +filteredname[src]='\\0'; +if (filtered==1) { + int pos=o->position()-1; + if (pos<0) pos=0; + o->value(filteredname); + o->position(pos,pos); +}} + xywh {100 35 390 20} labelsize 12 when 1 textsize 12 + code0 {o->maximum_size(64);} + code1 {o->value("Proj Name"); o->take_focus();} + } + Fl_Box {} { + label {Please specify the name for the new project below:} + xywh {5 8 485 19} labelfont 1 labelsize 12 align 20 + } + } + } +} 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 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0107 +header_name {.h} +code_name {.cxx} +decl {\#include } {public +} + +decl {\#include } {public +} + +class dialog_newsong {open +} { + decl {int buttonclicked;} {public + } + decl {char songname[65];} {public + } + decl {unsigned long songlength_in_samples;} {public + } + decl {__uint32 samplerate;} {public + } + decl {__uint32 trackcount;} {public + } + decl {int mode;} {public + } + decl {int useasrange;} {public + } + decl {int locnum;} {} + decl {int subsecmax;} {} + Function {make_window()} {open + } { + Fl_Window {} { + label {New song} open + xywh {212 241 500 180} type Double color 52 + code0 {buttonclicked=0; mode=2; songname[0]='\\0';} + code1 {subsecmax=29; samplerate=44100; trackcount=24;} + code2 {setuiloc(0);} modal visible + } { + Fl_Button button_ok { + label OK + callback {buttonclicked=1; //OK +strncpy(songname,currname->value(),64); +songlength_in_samples=getsonglen(); +Fl_Window * x = Fl::first_window(); +x->~Fl_Window();} + xywh {345 155 70 20} labelsize 12 + } + Fl_Button button_cancel { + label Cancel + callback {buttonclicked=2; //Cancel +useasrange=0; +Fl_Window * x = Fl::first_window(); +x->~Fl_Window();} + xywh {420 155 70 20} labelsize 12 + } + Fl_Input hr { + label {Length: } + callback {setuiloc(getsonglen());} + xywh {100 130 50 20} type Int labelsize 12 textsize 12 + code0 {o->maximum_size(2);} + } + Fl_Input min { + label {:} + callback {setuiloc(getsonglen());} + xywh {160 130 45 20} type Int labelfont 1 labelsize 12 textsize 12 + code0 {o->maximum_size(2);} + } + Fl_Input sec { + label {:} + callback {setuiloc(getsonglen());} + xywh {215 130 45 20} type Int labelfont 1 labelsize 12 textsize 12 + code0 {o->maximum_size(2);} + } + Fl_Input subsec { + label {.} + callback {setuiloc(getsonglen());} + xywh {270 130 60 20} type Int labelfont 1 labelsize 12 textsize 12 + code0 {o->maximum_size(5);} + } + Fl_Button button_mode { + label Frames + callback {setplchan(); + +mode=(mode+1)%3; +switch(mode) { + case 0: + { + o->label("Sec/100"); + subsecmax=99; + break; + } + case 1: + { + + if ((pchan /lchan)==2) { + o->label("2*Sams"); + } else { + o->label("Samples"); + } + subsecmax=samplerate/(pchan/lchan); + break; + } + case 2: + { + o->label("Frames"); + subsecmax=29; + break; + } +} +setuiloc(songlength_in_samples);} + xywh {270 110 60 20} labelsize 12 align 18 + } + Fl_Box {} { + label Hr + xywh {100 113 50 17} labelsize 12 + } + Fl_Box {} { + label Min + xywh {160 113 45 17} labelsize 12 + } + Fl_Box {} { + label Sec + xywh {215 113 45 17} labelsize 12 + } + Fl_Input currname { + label {Song name:} + callback {char filteredname[65]; +int x=strlen(o->value()); +if (x>64) { x=64; } +int src=0; +int filtered=0; +for (int i=0;ivalue()[i]=='\\\\') + || (o->value()[i]=='/') + || (o->value()[i]==':') + || (o->value()[i]=='*') + || (o->value()[i]=='?') + || (o->value()[i]=='"') + || (o->value()[i]=='<') + || (o->value()[i]=='>') + || (o->value()[i]=='\\\\') + || (o->value()[i]=='|')) + { + filtered=1; + continue; + } + filteredname[src]=o->value()[i]; + src++; +} +filteredname[src]='\\0'; +if (filtered==1) { + int pos=o->position()-1; + if (pos<0) pos=0; + o->value(filteredname); + o->position(pos,pos); +}} + xywh {100 35 390 20} labelsize 12 when 1 textsize 12 + code0 {o->maximum_size(64);} + code1 {o->value("Song Name"); o->take_focus();} + } + Fl_Choice ratechoice { + label {Sample rate:} open + xywh {100 60 145 20} down_box BORDER_BOX labelsize 12 textsize 12 + code0 {o->value(0);} + } { + MenuItem {} { + label {44100 Hz} + callback {samplerate=44100; setuiloc(getsonglen());} + xywh {35 35 36 21} labelsize 12 + } + MenuItem {} { + label {48000 Hz} + callback {samplerate=48000;setuiloc(getsonglen());} + xywh {45 45 36 21} labelsize 12 + } + MenuItem {} { + label {88200 Hz} + callback {samplerate=88200; setuiloc(getsonglen()); +if (numtracks->value()>7) +{ + numtracks->value(7); + trackcount=12; +}} + xywh {55 55 36 21} labelsize 12 + } + MenuItem {} { + label {96000 Hz} + callback {samplerate=96000; setuiloc(getsonglen()); +if (numtracks->value()>7) +{ + numtracks->value(7); + trackcount=12; +}} + xywh {65 65 36 21} labelsize 12 + } + } + Fl_Choice numtracks { + label {\# of Tracks:} open + xywh {100 85 145 20} down_box BORDER_BOX labelsize 12 textsize 12 + code0 {o->value(10);} + } { + MenuItem {} { + label 1 + callback {trackcount=1;} + xywh {45 45 36 21} labelsize 12 + } + MenuItem {} { + label 2 + callback {trackcount=2;} + xywh {55 55 36 21} labelsize 12 + } + MenuItem {} { + label 3 + callback {trackcount=3;} + xywh {65 65 36 21} labelsize 12 + } + MenuItem {} { + label 4 + callback {trackcount=4;} + xywh {75 75 36 21} labelsize 12 + } + MenuItem {} { + label 6 + callback {trackcount=6;} + xywh {85 85 36 21} labelsize 12 + } + MenuItem {} { + label 8 + callback {trackcount=8;} + xywh {95 95 36 21} labelsize 12 + } + MenuItem {} { + label 9 + callback {trackcount=9;} + xywh {105 105 36 21} labelsize 12 + } + MenuItem {} { + label 12 + callback {trackcount=12;} + xywh {105 105 36 21} labelsize 12 + } + MenuItem {} { + label 16 + callback {trackcount=16; +if (samplerate>=88200) +{ + trackcount=12; + numtracks->value(7); +}} + xywh {115 115 36 21} labelsize 12 + } + MenuItem {} { + label 18 + callback {trackcount=18; +if (samplerate>=88200) +{ + trackcount=12; + numtracks->value(7); +}} + xywh {125 125 36 21} labelsize 12 + } + MenuItem {} { + label 24 + callback {trackcount=24; +if (samplerate>=88200) +{ + trackcount=12; + numtracks->value(7); +}} + xywh {135 135 36 21} labelsize 12 + } + } + Fl_Box {} { + label {Please specify the parameters for the new song below:} + xywh {5 8 485 19} labelfont 1 labelsize 12 align 20 + } + } + } + Function {setuiloc(__uint32 offset)} {open return_type void + } { + code {setplchan(); +unsigned int chmult=(pchan/lchan); +unsigned long realrate=samplerate/chmult; + +string* strhr=Convert::int2str(hd24song::display_hours(offset,realrate)); +hr->value(strhr->c_str()); +delete strhr; + +string* strmin=Convert::int2str(hd24song::display_minutes(offset,realrate)); +min->value(strmin->c_str()); +delete strmin; + +string* strsec=Convert::int2str(hd24song::display_seconds(offset,realrate)); +sec->value(strsec->c_str()); +delete strsec; + +string* strsubsec; + +long subseconds=hd24song::display_subseconds(offset,realrate); +long subsecval; +setplchan(); + +switch(mode) { + case 0: subsecval=((subseconds*100)/ realrate ); break; + case 1: subsecval=(subseconds); break; + case 2: subsecval=((subseconds*30)/realrate ); break; + default: subsecval=0; +} +strsubsec=Convert::int2str(subsecval); +subsec->value(strsubsec->c_str()); +delete strsubsec;} {} + } + Function {setplchan()} {open + } { + code {lchan = trackcount; +if (this->samplerate>=88200) { + pchan=lchan*2; +} else { + pchan=lchan; +}} {} + } + decl {int pchan;} {} + decl {int lchan;} {} + Function {getsonglen()} {open return_type __uint32 + } { + code {setplchan(); +unsigned int chmult=(pchan/lchan); +unsigned long realrate=samplerate/chmult; + +long frames=0; +switch(mode) { + case 0: frames=100; break; + case 1: frames=realrate; break; + case 2: frames=30; break; +} + +__uint64 mylocpoint=((__uint64)3600* (__uint64)strtol( hr->value(),0,10) ) + +((__uint64) 60* (__uint64)strtol(min->value(),0,10) ) + +((__uint64) 1* (__uint64)strtol(sec->value(),0,10) ) + ; + +mylocpoint=(__uint64)((__uint64)realrate*(__uint64)mylocpoint); + +mylocpoint+=(__uint64)(strtol(subsec->value(),0,10)*samplerate/(frames*chmult)); + +if (mylocpoint>0xFFFFFFFF) { + mylocpoint=0xFFFFFFFF; +} +return (__uint32)mylocpoint;} {selected + } + } +} 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 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0107 +header_name {.h} +code_name {.cxx} +decl {\#include } {public +} + +decl {\#include } {public +} + +class dialog_options {open +} { + decl {int buttonclicked;} {public + } + decl {hd24song* currsong;} {} + decl {string* itemname;} {public + } + Function {~dialog_options()} {open + } { + code {if (itemname!=NULL) delete itemname;} {} + } + decl {int locnum;} {} + Function {make_window()} {open + } { + Fl_Window optionswindow { + label options open + xywh {420 519 565 145} type Double color 52 hide + code0 {buttonclicked=0;} modal + } { + Fl_Tabs {} {open + xywh {0 0 565 145} + } { + Fl_Group {} { + label Catalog open + xywh {0 20 565 125} labelsize 12 hide + } { + Fl_Check_Button {} { + label {Include locate point information in drive catalog} + xywh {5 25 550 15} down_box DOWN_BOX labelsize 12 deactivate + } + Fl_Button button_catalogapply { + label Apply + callback {buttonclicked=1; //OK +char dest[66]; +strncpy(&dest[0],currname->value(),64); +dest[64]='\\0'; +itemname=new string(dest); +Fl_Window * x = Fl::first_window(); +x->~Fl_Window();} + xywh {480 110 70 20} labelsize 12 + } + Fl_Check_Button {} { + label {Keep catalog sorted alphabetically} + xywh {5 45 550 15} down_box DOWN_BOX labelsize 12 deactivate + } + } + Fl_Group {} { + label Transfers open + xywh {0 20 565 125} labelsize 12 + } { + Fl_Button button_ok { + label Apply + callback {buttonclicked=1; //OK +char dest[66]; +strncpy(&dest[0],currname->value(),64); +dest[64]='\\0'; +itemname=new string(dest); +Fl_Window * x = Fl::first_window(); +x->~Fl_Window();} + xywh {480 110 70 20} labelsize 12 + } + Fl_Input currname { + label {Output file name:} + callback {char filteredname[65]; +int x=strlen(o->value()); +if (x>64) { x=64; } +int src=0; +int filtered=0; +for (int i=0;ivalue()[i]=='\\\\') + || (o->value()[i]=='/') + || (o->value()[i]==':') + || (o->value()[i]=='*') + || (o->value()[i]=='?') + || (o->value()[i]=='"') + || (o->value()[i]=='<') + || (o->value()[i]=='>') + || (o->value()[i]=='\\\\') + || (o->value()[i]=='|')) + { + filtered=1; + continue; + } + filteredname[src]=o->value()[i]; + src++; +} +filteredname[src]='\\0'; +if (filtered==1) { + int pos=o->position()-1; + if (pos<0) pos=0; + o->value(filteredname); + o->position(pos,pos); +}} + xywh {120 25 435 20} labelsize 12 when 1 textsize 12 + code0 {o->maximum_size(64);} + code1 {o->take_focus();} + } + Fl_Button button_transferhelp { + label Help + callback {fl_message("The following special sequences can be used:\\n" + "\\t\\tThe volume label of the drive\\n" + "\\t\\tThe name of the project\\n" + "\\t\\tThe name of the song\\n" + "\\t\\tThe sequence number of the project on disk\\n" + "\\t\\tThe sequence number of the song within the project\\n" + "\\t\\tThe track number being transferred\\n" + "\\tLikewise, prompt for offset before transfer\\n" + "\\t\\tCurrent date/time (YYYY-MM-DD HH:MI:SS)\\n" +);} selected + xywh {405 110 70 20} labelsize 12 + } + } + } + } + } + Function {dialog_options()} {open + } { + code {itemname=NULL;} {} + } +} 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 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0107 +header_name {.h} +code_name {.cxx} +decl {\#include } {public +} + +decl {\#include } {public +} + +class dialog_rename {open +} { + decl {int buttonclicked;} {public + } + decl {hd24song* currsong;} {} + decl {string* itemname;} {public + } + Function {~dialog_rename()} {open + } { + code {if (itemname!=NULL) delete itemname;} {} + } + decl {int locnum;} {} + Function {make_window(string* p_currname,string* p_title)} {open + } { + Fl_Window renamewindow { + label {Sample rate} open + xywh {277 310 490 75} type Double color 52 + code0 {buttonclicked=0;} + code1 {currname->value(p_currname->c_str());} + code2 {o->label(p_title->c_str());} modal visible + } { + Fl_Button button_ok { + label OK + callback {buttonclicked=1; //OK +char dest[66]; +strncpy(&dest[0],currname->value(),64); +dest[64]='\\0'; +itemname=new string(dest); +Fl_Window * x = Fl::first_window(); +x->~Fl_Window();} + xywh {330 40 70 25} + } + Fl_Button button_cancel { + label Cancel + callback {buttonclicked=2; //Cancel +Fl_Window * x = Fl::first_window(); +x->~Fl_Window();} + xywh {405 40 70 25} + } + Fl_Input currname { + label {New rate:} selected + xywh {90 10 385 20} labelsize 12 textsize 12 + code0 {o->maximum_size(64);} + code1 {o->take_focus();} + } + } + } +} 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 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0107 +header_name {.h} +code_name {.cxx} +decl {\#include } {public +} + +decl {\#include } {public +} + +class dialog_rename {open +} { + decl {int buttonclicked;} {public + } + decl {hd24song* currsong;} {} + decl {string* itemname;} {public + } + Function {~dialog_rename()} {open + } { + code {if (itemname!=NULL) delete itemname;} {} + } + decl {int locnum;} {} + Function {make_window(string* p_currname,string* p_title)} {open + } { + Fl_Window renamewindow { + label Rename open + xywh {111 127 490 75} type Double color 52 + code0 {buttonclicked=0;} + code1 {currname->value(p_currname->c_str());} + code2 {o->label(p_title->c_str());} modal visible + } { + Fl_Button button_ok { + label OK + callback {buttonclicked=1; //OK +char dest[66]; +strncpy(&dest[0],currname->value(),64); +dest[64]='\\0'; +itemname=new string(dest); +Fl_Window * x = Fl::first_window(); +x->~Fl_Window();} + xywh {330 40 70 25} + } + Fl_Button button_cancel { + label Cancel + callback {buttonclicked=2; //Cancel +Fl_Window * x = Fl::first_window(); +x->~Fl_Window();} + xywh {405 40 70 25} + } + Fl_Input currname { + label {New Name:} + callback {char filteredname[65]; +int x=strlen(o->value()); +if (x>64) { x=64; } +int src=0; +int filtered=0; +for (int i=0;ivalue()[i]=='\\\\') + || (o->value()[i]=='/') + || (o->value()[i]==':') + || (o->value()[i]=='*') + || (o->value()[i]=='?') + || (o->value()[i]=='"') + || (o->value()[i]=='<') + || (o->value()[i]=='>') + || (o->value()[i]=='\\\\') + || (o->value()[i]=='|')) + { + filtered=1; + continue; + } + filteredname[src]=o->value()[i]; + src++; +} +filteredname[src]='\\0'; +if (filtered==1) { + int pos=o->position()-1; + if (pos<0) pos=0; + o->value(filteredname); + o->position(pos,pos); +}} selected + xywh {90 10 385 20} labelsize 12 when 1 textsize 12 + code0 {o->maximum_size(64);} + code1 {o->take_focus();} + } + } + } +} 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 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0107 +header_name {.h} +code_name {.cxx} +decl {\#include } {public +} + +decl {\#include } {public +} + +class dialog_setlength {open +} { + decl {int buttonclicked;} {public + } + decl {unsigned long locpoint;} {public + } + decl {int mode;} {public + } + decl {int useasrange;} {public + } + decl {hd24song* currsong;} {} + decl {int locnum;} {} + decl {int subsecmax;} {} + Function {make_window(hd24song* p_currsong,int p_locnum)} {open + } { + Fl_Window {} { + label {Set song length} open selected + xywh {160 246 455 300} type Double color 52 + code0 {currsong=p_currsong; buttonclicked=0; mode=2;} + code1 {locpoint=currsong->songlength_in_samples();} + code2 {setuiloc(locpoint); subsecmax=29;} + code3 {p_locnum=p_locnum;} modal visible + } { + Fl_Button button_ok { + label OK + callback {buttonclicked=1; //OK +Fl_Window * x = Fl::first_window(); +x->~Fl_Window();} + xywh {300 270 70 20} labelsize 12 + } + Fl_Button button_cancel { + label Cancel + callback {buttonclicked=2; //Cancel +useasrange=0; +Fl_Window * x = Fl::first_window(); +x->~Fl_Window();} + xywh {375 270 70 20} labelsize 12 + } + Fl_Input hr { + label {New song length: } + callback {unsigned int chmult=(currsong->physical_channels()/currsong->logical_channels()); +unsigned long realrate=currsong->samplerate()/chmult; + +locpoint-=(unsigned long)(3600*realrate*(currsong->display_hours(locpoint))); +locpoint+=(unsigned long)(3600*realrate*(strtol(hr->value(),0,10))); +setuiloc(locpoint);} + xywh {150 65 50 20} type Int labelsize 12 textsize 12 + code0 {o->maximum_size(2);} + } + Fl_Input min { + label {:} + callback {unsigned int chmult=(currsong->physical_channels()/currsong->logical_channels()); +unsigned long realrate=currsong->samplerate()/chmult; + +locpoint-=(unsigned long)(60*realrate*(currsong->display_minutes(locpoint))); +locpoint+=(unsigned long)(60*realrate*(strtol(min->value(),0,10))); +setuiloc(locpoint);} + xywh {210 65 45 20} type Int labelfont 1 labelsize 12 textsize 12 + code0 {o->maximum_size(2);} + } + Fl_Input sec { + label {:} + callback {unsigned int chmult=(currsong->physical_channels()/currsong->logical_channels()); +unsigned long realrate=currsong->samplerate()/chmult; + +locpoint-=(unsigned long)(realrate*(currsong->display_seconds(locpoint))); +locpoint+=(unsigned long)(realrate*(strtol(sec->value(),0,10))); +setuiloc(locpoint);} + xywh {265 65 45 20} type Int labelfont 1 labelsize 12 textsize 12 + code0 {o->maximum_size(2);} + } + Fl_Input subsec { + label {.} + callback {if (strtol(subsec->value(),0,10)>subsecmax) { + string* strmax=Convert::int2str(subsecmax); + subsec->value(strmax->c_str()); + delete strmax; + +} + +unsigned int chmult=(currsong->physical_channels()/currsong->logical_channels()); +unsigned long realrate=currsong->samplerate()/chmult; + +long subseconds=currsong->display_subseconds(locpoint); + +locpoint-=subseconds; + +long frames=0; +switch(mode) { + case 0: frames=100; break; + case 1: frames=realrate; break; + case 2: frames=30; break; +} +locpoint+=(unsigned long)(strtol(subsec->value(),0,10)*currsong->samplerate()/(frames*chmult)); +setuiloc(locpoint);} + xywh {320 65 60 20} type Int labelfont 1 labelsize 12 textsize 12 + code0 {o->maximum_size(5);} + } + Fl_Button button_mode { + label Frames + callback {mode=(mode+1)%3; +switch(mode) { + case 0: + { + o->label("Sec/100"); + subsecmax=99; + break; + } + case 1: + { + + if ((currsong->physical_channels()/currsong->logical_channels())==2) { + o->label("2*Sams"); + } else { + o->label("Samples"); + } + subsecmax=currsong->samplerate()/(currsong->physical_channels()/currsong->logical_channels()); + break; + } + case 2: + { + o->label("Frames"); + subsecmax=29; + break; + } +} +setuiloc(locpoint);} + xywh {320 45 60 20} labelsize 12 align 18 + } + Fl_Box {} { + label Hr + xywh {150 48 50 17} labelsize 12 + } + Fl_Box {} { + label Min + xywh {210 48 45 17} labelsize 12 + } + Fl_Box {} { + label Sec + xywh {265 48 45 17} labelsize 12 + } + Fl_Box {} { + label {Set the approximate song length here. Round up when unsure.} + xywh {5 5 440 30} labelsize 12 align 20 + } + Fl_Box {} { + label {Note: This operation will requires about 40 MB of free space to write +recovery information to a header file on your computer. + +This operation WILL NOT write to your HD24 drive, and as such should +be completely safe, while permitting you to save your missing audio. +Once this operation is complete, you should TRANSFER ALL AUDIO +that you want to keep from the HD24 drive and then re-format it, +before recording any more audio to it. + +Cancel this dialog if you're not in need of a recovery.} + xywh {5 100 440 160} labelsize 12 align 21 + } + } + } + Function {setuiloc(unsigned long offset)} {open return_type void + } { + code {unsigned long maxoffset=0xFFFFFFFF; +if (offset>maxoffset) { + offset=maxoffset; + locpoint=offset; +} +string* strhr=Convert::int2str(currsong->display_hours(offset)); +hr->value(strhr->c_str()); +delete strhr; + +string* strmin=Convert::int2str(currsong->display_minutes(offset)); +min->value(strmin->c_str()); +delete strmin; + +string* strsec=Convert::int2str(currsong->display_seconds(offset)); +sec->value(strsec->c_str()); +delete strsec; + +string* strsubsec; + +long subseconds=currsong->display_subseconds(offset); +long subsecval; +switch(mode) { + case 0: subsecval=((subseconds*100)/ ( currsong->samplerate()/ (currsong->physical_channels()/currsong->logical_channels()) ) ); break; + case 1: subsecval=(subseconds); break; + case 2: subsecval=((subseconds*30)/( currsong->samplerate()/ (currsong->physical_channels()/currsong->logical_channels()) ) ); ; break; + default: subsecval=0; +} +strsubsec=Convert::int2str(subsecval); +subsec->value(strsubsec->c_str()); +delete strsubsec;} {} + } +} 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 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0107 +header_name {.h} +code_name {.cxx} +decl {\#include } {public +} + +decl {\#include } {public +} + +class dialog_setlocate {open +} { + decl {int buttonclicked;} {public + } + decl {unsigned long locpoint;} {public + } + decl {int mode;} {public + } + decl {int useasrange;} {public + } + decl {hd24song* currsong;} {} + decl {int locnum;} {} + decl {int subsecmax;} {} + Function {make_window(hd24song* p_currsong,int p_locnum)} {open + } { + Fl_Window {} { + label {Edit locate point} open + xywh {160 247 385 100} type Double color 52 + code0 {currsong=p_currsong; buttonclicked=0; mode=2; locnum=p_locnum;} + code1 {locpoint=currsong->getlocatepos(locnum); locname->value(currsong->getlocatename(locnum)->c_str());} + code2 {setuiloc(currsong->getlocatepos(locnum)); subsecmax=29;} + 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 + } { + Fl_Button button_ok { + label OK + callback {buttonclicked=1; //OK +char dest[10]; +strncpy(&dest[0],locname->value(),8); +dest[9]='\\0'; +string* newname=new string(dest); +currsong->setlocatename(locnum,*newname); +currsong->setlocatepos(locnum,locpoint); +useasrange=setasrange->value(); +delete newname; +Fl_Window * x = Fl::first_window(); +x->~Fl_Window();} + xywh {235 75 70 20} labelsize 12 + } + Fl_Button button_cancel { + label Cancel + callback {buttonclicked=2; //Cancel +useasrange=0; +Fl_Window * x = Fl::first_window(); +x->~Fl_Window();} + xywh {310 75 70 20} labelsize 12 + } + Fl_Input hr { + label {New locate point:} + callback {unsigned int chmult=(currsong->physical_channels()/currsong->logical_channels()); +unsigned long realrate=currsong->samplerate()/chmult; + +locpoint-=(unsigned long)(3600*realrate*(currsong->display_hours(locpoint))); +locpoint+=(unsigned long)(3600*realrate*(strtol(hr->value(),0,10))); +setuiloc(locpoint);} + xywh {150 45 50 20} type Int labelsize 12 textsize 12 + code0 {o->maximum_size(2);} + } + Fl_Input min { + label {:} + callback {unsigned int chmult=(currsong->physical_channels()/currsong->logical_channels()); +unsigned long realrate=currsong->samplerate()/chmult; + +locpoint-=(unsigned long)(60*realrate*(currsong->display_minutes(locpoint))); +locpoint+=(unsigned long)(60*realrate*(strtol(min->value(),0,10))); +setuiloc(locpoint);} + xywh {210 45 45 20} type Int labelfont 1 labelsize 12 textsize 12 + code0 {o->maximum_size(2);} + } + Fl_Input sec { + label {:} + callback {unsigned int chmult=(currsong->physical_channels()/currsong->logical_channels()); +unsigned long realrate=currsong->samplerate()/chmult; + +locpoint-=(unsigned long)(realrate*(currsong->display_seconds(locpoint))); +locpoint+=(unsigned long)(realrate*(strtol(sec->value(),0,10))); +setuiloc(locpoint);} + xywh {265 45 45 20} type Int labelfont 1 labelsize 12 textsize 12 + code0 {o->maximum_size(2);} + } + Fl_Input subsec { + label {.} + callback {if (strtol(subsec->value(),0,10)>subsecmax) { + string* strmax=Convert::int2str(subsecmax); + subsec->value(strmax->c_str()); + delete strmax; + +} + +unsigned int chmult=(currsong->physical_channels()/currsong->logical_channels()); +unsigned long realrate=currsong->samplerate()/chmult; + +long subseconds=currsong->display_subseconds(locpoint); + +locpoint-=subseconds; + +long frames=0; +switch(mode) { + case 0: frames=100; break; + case 1: frames=realrate; break; + case 2: frames=30; break; +} +locpoint+=(unsigned long)(strtol(subsec->value(),0,10)*currsong->samplerate()/(frames*chmult)); +setuiloc(locpoint);} + xywh {320 45 60 20} type Int labelfont 1 labelsize 12 textsize 12 + code0 {o->maximum_size(5);} + } + Fl_Button button_mode { + label Frames + callback {mode=(mode+1)%3; +switch(mode) { + case 0: + { + o->label("Sec/100"); + subsecmax=99; + break; + } + case 1: + { + + if ((currsong->physical_channels()/currsong->logical_channels())==2) { + o->label("2*Sams"); + } else { + o->label("Samples"); + } + subsecmax=currsong->samplerate()/(currsong->physical_channels()/currsong->logical_channels()); + break; + } + case 2: + { + o->label("Frames"); + subsecmax=29; + break; + } +} +setuiloc(locpoint);} + xywh {320 25 60 20} labelsize 12 align 18 + } + Fl_Input locname { + label {Location Name:} + callback {char templabel[10]; +strncpy(&templabel[0],o->value(),8); +templabel[8]='\\0'; +o->value(templabel);} + xywh {150 5 115 20} labelsize 12 textsize 12 + code0 {o->maximum_size(8);} + } + Fl_Check_Button setasrange { + label {Set as start of export range} + xywh {25 75 205 20} down_box DOWN_BOX value 1 labelsize 12 + } + Fl_Box {} { + label Hr + xywh {150 28 50 17} labelsize 12 + } + Fl_Box {} { + label Min + xywh {210 28 45 17} labelsize 12 + } + Fl_Box {} { + label Sec + xywh {265 28 45 17} labelsize 12 + } + } + } + Function {setuiloc(unsigned long offset)} {open return_type void + } { + code {unsigned long maxoffset=currsong->getlocatepos(25); +if (offset>maxoffset) { + offset=maxoffset; + locpoint=offset; +} +string* strhr=Convert::int2str(currsong->display_hours(offset)); +hr->value(strhr->c_str()); +delete strhr; + +string* strmin=Convert::int2str(currsong->display_minutes(offset)); +min->value(strmin->c_str()); +delete strmin; + +string* strsec=Convert::int2str(currsong->display_seconds(offset)); +sec->value(strsec->c_str()); +delete strsec; + +string* strsubsec; + +long subseconds=currsong->display_subseconds(offset); +long subsecval; +switch(mode) { + case 0: subsecval=((subseconds*100)/ ( currsong->samplerate()/ (currsong->physical_channels()/currsong->logical_channels()) ) ); break; + case 1: subsecval=(subseconds); break; + case 2: subsecval=((subseconds*30)/( currsong->samplerate()/ (currsong->physical_channels()/currsong->logical_channels()) ) ); ; break; + default: subsecval=0; +} +strsubsec=Convert::int2str(subsecval); +subsec->value(strsubsec->c_str()); +delete strsubsec;} {selected + } + } +} 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 @@ +#define MAINDEBUG 0 +#include +#include +#include +#include "ui_hd24connect.h" +#include +#include +#include //dave +#ifdef LINUX +#include //dave +#endif +#include "images/hd24connect_64x64.xpm" //dave +#include +#include +#include +#include +#ifndef MAX_PATH +#define MAX_PATH 127 +#endif + +#ifdef WINDOWS +#include +#define IDI_ICON1 101 +#endif +string device; +string headerfilename; +int force; +int maintmode; +int wavefixmode; +int testmode; +#ifdef LINUX +#define TIMEOUT 0.03 +#endif +#define ARGDEV "--dev=" +#define ARGHEADER "--header=" +#define ARGFORCE "--force" +#define ARGMAINT "--maint" +#define ARGWAVEFIX "--wavefix" +#define ARGTEST "--test" + +#include "selftest.cpp" + +int parsecommandline(int argc, char ** argv) +{ + int invalid=0; + force=0; + maintmode=0; + wavefixmode=0; + testmode=0; + device=""; + for (int c=1;cc_str(),hd24fs::MODE_RDWR); + } else { + cout << "Trying to use " << device << " as hd24 device." << endl; + sysob=new hd24fs(imagedir->c_str(),hd24fs::MODE_RDWR,&device,(force==1)); + if (!(sysob->isOpen())) + { + if (!force) { + cout << "Cannot open hd24 device" << endl; + delete sysob; + return 1; + } + } + } + delete imagedir; + if (headerfilename!="") + { + if (!(sysob->useheaderfile(headerfilename))) + { + cout << "Couldn't load header file "<setmaintenancemode(maintmode); + sysob->setwavefixmode(wavefixmode); +#if (MAINDEBUG==1) + cout << "mdb(3c)" << endl; +#endif + Fl_Window *window = ui.make_window(sysob); +#if (MAINDEBUG==1) + cout << "mdb(3d)" << endl; +#endif +#ifdef WINDOWS + + window->icon((char *)LoadIcon(fl_display,MAKEINTRESOURCE(IDI_ICON1))); +#endif + window->end(); + window->show(); //argc, argv); + +#ifdef LINUX //dave + Pixmap p, mask; + XpmCreatePixmapFromData(fl_display,DefaultRootWindow(fl_display),(char **)hd24connect_xpm, &p, &mask, NULL); + +/* +FLTK support for transparent background is broken. So instead of this: +window->icon((char *)p); +We will write the following: */ +XWMHints *hints=NULL; +hints = XGetWMHints(fl_display, fl_xid(window)); +hints->icon_pixmap = p; +hints->icon_mask = mask; +hints->flags = IconPixmapHint | IconMaskHint; +XSetWMHints(fl_display, fl_xid(window), hints); +/* -- end of transparency fix */ +#endif +#if (MAINDEBUG==1) + cout << "mdb(3)" << endl; +#endif +#if (MAINDEBUG==1) + cout << "mdb(4)" << endl; +#endif + if (!(sysob->isOpen())) + { + window->deactivate(); + fl_message("No valid HD24 drive is connected to the system.\nUse the File menu to resolve this problem."); + window->activate(); + } + // run normally. + result= Fl::run(); + ui.control->ready(0); +#ifndef WINDOWS + cout << "Thank you for using HD24connect." << endl; +#endif +// ui.finish(); + +#ifdef hints + if (hints!=NULL) + { + delete hints; + } +#endif + return result; +} diff --git a/src/frontend/hd24connect.ico b/src/frontend/hd24connect.ico new file mode 100644 index 0000000..72a6e89 Binary files /dev/null and b/src/frontend/hd24connect.ico differ diff --git a/src/frontend/images/7seg_0.gif b/src/frontend/images/7seg_0.gif new file mode 100644 index 0000000..58e66fe Binary files /dev/null and b/src/frontend/images/7seg_0.gif differ diff --git a/src/frontend/images/7seg_1.gif b/src/frontend/images/7seg_1.gif new file mode 100644 index 0000000..07c0b19 Binary files /dev/null and b/src/frontend/images/7seg_1.gif differ diff --git a/src/frontend/images/7seg_2.gif b/src/frontend/images/7seg_2.gif new file mode 100644 index 0000000..6b8061c Binary files /dev/null and b/src/frontend/images/7seg_2.gif differ diff --git a/src/frontend/images/7seg_3.gif b/src/frontend/images/7seg_3.gif new file mode 100644 index 0000000..60556e5 Binary files /dev/null and b/src/frontend/images/7seg_3.gif differ diff --git a/src/frontend/images/7seg_4.gif b/src/frontend/images/7seg_4.gif new file mode 100644 index 0000000..c3e1e96 Binary files /dev/null and b/src/frontend/images/7seg_4.gif differ diff --git a/src/frontend/images/7seg_5.gif b/src/frontend/images/7seg_5.gif new file mode 100644 index 0000000..927bf60 Binary files /dev/null and b/src/frontend/images/7seg_5.gif differ diff --git a/src/frontend/images/7seg_6.gif b/src/frontend/images/7seg_6.gif new file mode 100644 index 0000000..5dbf489 Binary files /dev/null and b/src/frontend/images/7seg_6.gif differ diff --git a/src/frontend/images/7seg_7.gif b/src/frontend/images/7seg_7.gif new file mode 100644 index 0000000..f7e215b Binary files /dev/null and b/src/frontend/images/7seg_7.gif differ diff --git a/src/frontend/images/7seg_8.gif b/src/frontend/images/7seg_8.gif new file mode 100644 index 0000000..4fd1568 Binary files /dev/null and b/src/frontend/images/7seg_8.gif differ diff --git a/src/frontend/images/7seg_9.gif b/src/frontend/images/7seg_9.gif new file mode 100644 index 0000000..42cefe9 Binary files /dev/null and b/src/frontend/images/7seg_9.gif differ diff --git a/src/frontend/images/HD24_matrix.gif b/src/frontend/images/HD24_matrix.gif new file mode 100644 index 0000000..33dfe22 Binary files /dev/null and b/src/frontend/images/HD24_matrix.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_100.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_101.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_102.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_103.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_104.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_105.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_106.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_107.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_108.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_109.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_110.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_111.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_112.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_113.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_114.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_115.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_116.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_117.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_118.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_119.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_120.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_121.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_122.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_123.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_124.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_125.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_126.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_127.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_32.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_33.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_34.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_35.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_36.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_37.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_38.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_39.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_40.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_41.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_42.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_43.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_44.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_45.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_46.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_47.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_48.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_49.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_50.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_51.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_52.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_53.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_54.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_55.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_56.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_57.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_58.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_59.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_60.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_61.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_62.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_63.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_64.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_65.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_66.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_67.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_68.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_69.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_70.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_71.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_72.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_73.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_74.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_75.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_76.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_77.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_78.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_79.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_80.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_81.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_82.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_83.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_84.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_85.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_86.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_87.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_88.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_89.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_90.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_91.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_92.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_93.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_94.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_95.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_96.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_97.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_98.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_99.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_arrowleft.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_arrowright.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_realsize.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_writeenabled.gif 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 Binary files /dev/null and b/src/frontend/images/HD24_matrix_writeprotected.gif differ diff --git a/src/frontend/images/aqua.bmp b/src/frontend/images/aqua.bmp new file mode 100644 index 0000000..3ad5445 Binary files /dev/null and b/src/frontend/images/aqua.bmp differ diff --git a/src/frontend/images/aqua.rar b/src/frontend/images/aqua.rar new file mode 100644 index 0000000..63e877e Binary files /dev/null and b/src/frontend/images/aqua.rar differ diff --git a/src/frontend/images/aquabutton_down.gif b/src/frontend/images/aquabutton_down.gif new file mode 100644 index 0000000..ecf4092 Binary files /dev/null and b/src/frontend/images/aquabutton_down.gif differ diff --git a/src/frontend/images/aquabutton_up.gif b/src/frontend/images/aquabutton_up.gif new file mode 100644 index 0000000..2b12ec2 Binary files /dev/null and b/src/frontend/images/aquabutton_up.gif differ diff --git a/src/frontend/images/button.gif b/src/frontend/images/button.gif new file mode 100644 index 0000000..070d82b Binary files /dev/null and b/src/frontend/images/button.gif differ diff --git a/src/frontend/images/button.xcf b/src/frontend/images/button.xcf new file mode 100644 index 0000000..d80fd3c Binary files /dev/null and b/src/frontend/images/button.xcf differ diff --git a/src/frontend/images/button_ffwd.gif b/src/frontend/images/button_ffwd.gif new file mode 100644 index 0000000..f09258e Binary files /dev/null and b/src/frontend/images/button_ffwd.gif 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 Binary files /dev/null and b/src/frontend/images/button_ffwd_dn.gif differ diff --git a/src/frontend/images/button_lrc.gif b/src/frontend/images/button_lrc.gif new file mode 100644 index 0000000..f2ab406 Binary files /dev/null and b/src/frontend/images/button_lrc.gif 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 Binary files /dev/null and b/src/frontend/images/button_lrc_dn.gif 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 Binary files /dev/null and b/src/frontend/images/button_lrc_led.gif 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 Binary files /dev/null and b/src/frontend/images/button_lrc_led_dn.gif 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 Binary files /dev/null and b/src/frontend/images/button_lrc_led_on.gif 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 Binary files /dev/null and b/src/frontend/images/button_lrc_led_on_dn.gif differ diff --git a/src/frontend/images/button_mute.gif b/src/frontend/images/button_mute.gif new file mode 100644 index 0000000..b29e443 Binary files /dev/null and b/src/frontend/images/button_mute.gif 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 Binary files /dev/null and b/src/frontend/images/button_mute_dn.gif differ diff --git a/src/frontend/images/button_play.gif b/src/frontend/images/button_play.gif new file mode 100644 index 0000000..5e26985 Binary files /dev/null and b/src/frontend/images/button_play.gif 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 Binary files /dev/null and b/src/frontend/images/button_play_dn.gif differ diff --git a/src/frontend/images/button_rec.gif b/src/frontend/images/button_rec.gif new file mode 100644 index 0000000..af2ad76 Binary files /dev/null and b/src/frontend/images/button_rec.gif 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 Binary files /dev/null and b/src/frontend/images/button_rec_dn.gif differ diff --git a/src/frontend/images/button_rew.gif b/src/frontend/images/button_rew.gif new file mode 100644 index 0000000..1dd8501 Binary files /dev/null and b/src/frontend/images/button_rew.gif 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 Binary files /dev/null and b/src/frontend/images/button_rew_dn.gif differ diff --git a/src/frontend/images/button_small.gif b/src/frontend/images/button_small.gif new file mode 100644 index 0000000..762af63 Binary files /dev/null and b/src/frontend/images/button_small.gif 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 Binary files /dev/null and b/src/frontend/images/button_small_dn.gif differ diff --git a/src/frontend/images/button_solo.gif b/src/frontend/images/button_solo.gif new file mode 100644 index 0000000..f70004e Binary files /dev/null and b/src/frontend/images/button_solo.gif 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 Binary files /dev/null and b/src/frontend/images/button_solo_dn.gif differ diff --git a/src/frontend/images/button_stop.gif b/src/frontend/images/button_stop.gif new file mode 100644 index 0000000..06b5581 Binary files /dev/null and b/src/frontend/images/button_stop.gif 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 Binary files /dev/null and b/src/frontend/images/button_stop_dn.gif 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 Binary files /dev/null and b/src/frontend/images/button_stop_uplit.gif differ diff --git a/src/frontend/images/ch21.gif b/src/frontend/images/ch21.gif new file mode 100644 index 0000000..2aece61 Binary files /dev/null and b/src/frontend/images/ch21.gif differ diff --git a/src/frontend/images/ch21.png b/src/frontend/images/ch21.png new file mode 100644 index 0000000..b564294 Binary files /dev/null and b/src/frontend/images/ch21.png differ diff --git a/src/frontend/images/down.gif b/src/frontend/images/down.gif new file mode 100644 index 0000000..6320f2a Binary files /dev/null and b/src/frontend/images/down.gif differ diff --git a/src/frontend/images/fader.gif b/src/frontend/images/fader.gif new file mode 100644 index 0000000..5ee05a2 Binary files /dev/null and b/src/frontend/images/fader.gif differ diff --git a/src/frontend/images/ffwd.gif b/src/frontend/images/ffwd.gif new file mode 100755 index 0000000..8029722 Binary files /dev/null and b/src/frontend/images/ffwd.gif differ diff --git a/src/frontend/images/hd24connect.png b/src/frontend/images/hd24connect.png new file mode 100755 index 0000000..4ad7bc6 Binary files /dev/null and b/src/frontend/images/hd24connect.png 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 @@ +/* XPM */ +const char * hd24connect_xpm[] = { +"32 32 3 1", +" c None", +". c #FFFFFF", +"+ c #000000", +"....... .................. ", +".+++++. .+++++.+++++++++++.. ", +".+++++. .+++++..++++++++++++. ", +".+++++.....+++++...++++++++++++.", +".+++++++++++++++............+++.", +".+++++++++++++++.++++.......+++.", +".+++++.....+++++.++++++++++++++.", +".+++++. .+++++.+++++++++++++. ", +".+++++. .+++++.+++++++++++.. ", +"....... ...... ........... ", +" ", +" ", +" ", +" ............ ... ..... ", +" .++++++++++++. .+++. .+++++.", +".++++++++++++++. .++++. .+++++.", +" .........+++++. .+++.....+++++.", +" .+++++++++++++..++++++++++++++.", +".+++++++++++++. .++++++++++++++.", +".+++++..........+++++++++++++++.", +".++++++++++++++...........+++++.", +" .+++++++++++++. .+++++.", +" ............. .......", +" ", +" ", +"................................", +"..++.+++.+..+.+..+.+++..++.+++++", +".+...+.+.++.+.++.+.+...+.....+..", +".+...+.+.+.++.+.++.++..+.....+..", +".+...+.+.+..+.+..+.+...+.....+..", +"..++.+++.+..+.+..+.+++..++...+..", +"................................"}; 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 @@ +/* XPM */ +const char * hd24connect_xpm[] = { +"64 64 288 2", +" c None", +". c #3B412D", +"+ c #343913", +"@ c #272E1D", +"# c #0C161A", +"$ c #10191D", +"% c #303437", +"& c #323A3E", +"* c #1C1C1C", +"= c #000000", +"- c #42161A", +"; c #121415", +"> c #4B1215", +", c #0F1011", +"' c #0C0D0E", +") c #070708", +"! c #040506", +"~ c #08090A", +"{ c #0A0C0C", +"] c #020203", +"^ c #060809", +"/ c #FAFAFA", +"( c #FEFEFE", +"_ c #C5C7C8", +": c #6D6E6F", +"< c #4D4F50", +"[ c #828384", +"} c #FCFDFD", +"| c #F0F2F2", +"1 c #CCCFD0", +"2 c #8E9091", +"3 c #292A2A", +"4 c #222222", +"5 c #FBFBFC", +"6 c #FFFFFF", +"7 c #C6C8C8", +"8 c #6E6F70", +"9 c #4E4F50", +"0 c #252626", +"a c #D1D2D3", +"b c #F7F7F7", +"c c #444546", +"d c #16191B", +"e c #222728", +"f c #1D2122", +"g c #040505", +"h c #393A3B", +"i c #656767", +"j c #7B7C7D", +"k c #858686", +"l c #868686", +"m c #888989", +"n c #F7F8F8", +"o c #A8AAAA", +"p c #050606", +"q c #EEF0F0", +"r c #AEAEAE", +"s c #C8CACB", +"t c #080A0A", +"u c #737475", +"v c #070808", +"w c #0D0E10", +"x c #030404", +"y c #010101", +"z c #141516", +"A c #131516", +"B c #FCFCFC", +"C c #868889", +"D c #FAFAFB", +"E c #383B3C", +"F c #090A0A", +"G c #262829", +"H c #898A8B", +"I c #393C3C", +"J c #28292A", +"K c #E4E5E5", +"L c #848586", +"M c #BFC1C1", +"N c #050506", +"O c #2B3235", +"P c #212629", +"Q c #262A2D", +"R c #161617", +"S c #7A7C7D", +"T c #060606", +"U c #424546", +"V c #101212", +"W c #EFF1F1", +"X c #352427", +"Y c #F9FAFA", +"Z c #F8F8F8", +"` c #868888", +" . c #020202", +".. c #ECEDEE", +"+. c #949696", +"@. c #0A0B0B", +"#. c #232323", +"$. c #727374", +"%. c #747575", +"&. c #5A5C5C", +"*. c #38393A", +"=. c #727373", +"-. c #212223", +";. c #3E3F40", +">. c #707172", +",. c #5C5C5D", +"'. c #353637", +"). c #464A4B", +"!. c #202223", +"~. c #343637", +"{. c #191A1B", +"]. c #423135", +"^. c #1C1D1E", +"/. c #1A1D1E", +"(. c #3C3F41", +"_. c #212A2D", +":. c #414146", +"<. c #35312B", +"[. c #282E20", +"}. c #2F2B26", +"|. c #394246", +"1. c #333739", +"2. c #373539", +"3. c #3D4044", +"4. c #151A19", +"5. c #161819", +"6. c #020303", +"7. c #44171A", +"8. c #24292C", +"9. c #1F2427", +"0. c #151819", +"a. c #4A4E50", +"b. c #252728", +"c. c #040606", +"d. c #0A0A0B", +"e. c #0A0B0C", +"f. c #0D0E0E", +"g. c #030304", +"h. c #000101", +"i. c #343434", +"j. c #242526", +"k. c #989A9B", +"l. c #D4D6D7", +"m. c #EDEEEE", +"n. c #F2F3F3", +"o. c #F3F4F4", +"p. c #E9EAEB", +"q. c #CCCECF", +"r. c #949697", +"s. c #363738", +"t. c #040404", +"u. c #212424", +"v. c #F1F2F2", +"w. c #E8EAEA", +"x. c #BEC0C2", +"y. c #101010", +"z. c #050607", +"A. c #C6C9CA", +"B. c #DADADB", +"C. c #797B7C", +"D. c #272829", +"E. c #DEDFDF", +"F. c #0A0A0A", +"G. c #2D3033", +"H. c #F4F4F5", +"I. c #D0D2D3", +"J. c #121313", +"K. c #949596", +"L. c #D5D6D7", +"M. c #F5F6F6", +"N. c #101112", +"O. c #AEB0B1", +"P. c #595A5C", +"Q. c #343739", +"R. c #303537", +"S. c #131414", +"T. c #9B9D9E", +"U. c #FAFCFC", +"V. c #161618", +"W. c #3C3E3E", +"X. c #C1C2C3", +"Y. c #F0F1F2", +"Z. c #A0A2A4", +"`. c #B0B1B2", +" + c #434646", +".+ c #121314", +"++ c #EFF0F1", +"@+ c #030303", +"#+ c #454647", +"$+ c #959798", +"%+ c #E6E7E8", +"&+ c #F2F4F4", +"*+ c #FAFBFB", +"=+ c #E7E8E9", +"-+ c #2A2C2D", +";+ c #ADAFB0", +">+ c #FEFEFF", +",+ c #FDFEFE", +"'+ c #C8C9CA", +")+ c #151616", +"!+ c #C7C8C9", +"~+ c #D1D2D2", +"{+ c #999A9A", +"]+ c #98999A", +"^+ c #87898A", +"/+ c #656667", +"(+ c #2C2D2E", +"_+ c #333435", +":+ c #646666", +"<+ c #818282", +"[+ c #8F9192", +"}+ c #939495", +"|+ c #959697", +"1+ c #F8F9F9", +"2+ c #242626", +"3+ c #8C8D8E", +"4+ c #8F9091", +"5+ c #0B0C0C", +"6+ c #2C3032", +"7+ c #1D1F20", +"8+ c #131415", +"9+ c #F4F4F4", +"0+ c #ECEEEE", +"a+ c #E8EAEB", +"b+ c #161818", +"c+ c #1E1F20", +"d+ c #2F2F2F", +"e+ c #545556", +"f+ c #D0D1D2", +"g+ c #161718", +"h+ c #252627", +"i+ c #545656", +"j+ c #727474", +"k+ c #838484", +"l+ c #7A7C7C", +"m+ c #6B6D6D", +"n+ c #2B2E31", +"o+ c #060707", +"p+ c #2A2E32", +"q+ c #1F2426", +"r+ c #212425", +"s+ c #101213", +"t+ c #0E1010", +"u+ c #222425", +"v+ c #303233", +"w+ c #585D5E", +"x+ c #2C2C2C", +"y+ c #0B0B0B", +"z+ c #262626", +"A+ c #242424", +"B+ c #202020", +"C+ c #191919", +"D+ c #303030", +"E+ c #1B1B1B", +"F+ c #212121", +"G+ c #171717", +"H+ c #292929", +"I+ c #080808", +"J+ c #090909", +"K+ c #0E0E0E", +"L+ c #070707", +"M+ c #050505", +"N+ c #121212", +"O+ c #272727", +"P+ c #3D3D3D", +"Q+ c #282828", +"R+ c #0D0D0D", +"S+ c #181818", +"T+ c #252525", +"U+ c #323232", +"V+ c #2E2E2E", +"W+ c #3C3C3C", +"X+ c #1F1F1F", +"Y+ c #111111", +"Z+ c #2B2B2B", +"`+ c #1E1E1E", +" @ c #141414", +".@ c #626262", +"+@ c #161616", +"@@ c #5E5E5E", +"#@ c #414141", +"$@ c #131313", +"%@ c #1A1A1A", +"&@ c #0F0F0F", +"*@ c #393939", +"=@ c #383838", +"-@ c #565656", +";@ c #3A3A3A", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +" ", +". + + + + + + + + + + + + + + + + + + @ # # # # # # # # # # # $ + + + + + + + + + + + + + + + % & ", +"* = = = = = = = = = = = - = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = ; > ", +"* = = , , , , , , ' = = - = = ) , , , , , , ! = = = ~ , , , , , , , , , , , , , , , , , , , , , { ] = = = = , ", +"* = ^ / ( ( ( ( ( _ = = - = = : ( ( ( ( ( ( < = = = [ ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( ( } | 1 2 3 = = 4 ", +"* = ^ 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 = = ", +"* = ^ 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 = = ", +"* = ^ 5 6 6 6 6 6 7 = = = = = = = = = = = = = 8 6 6 6 6 6 6 9 = = = = = = = = = = = = = = = = = = = = = = = p q 6 6 6 6 6 r = = ", +"* = ^ 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 = = ", +"* = ^ 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 = = ", +"* = ^ 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 = = ", +"* = ^ 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 = = ", +"* = ^ 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 = = ", +"* = ^ 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 = = ", +"* = ^ 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 ` = .", +"* = ^ 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 ..+.@.= #.", +"* = x $.%.%.%.%.%.&.= = - = = *.%.%.%.%.%.=.-.= = = ;.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.%.>.,.'.F = = .).", +"* = = = = = = = = = = = - = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = !. ", +"~.{.{.{.{.{.{.{.{.{.{.{.]. {.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.{.^./.(._. ", +" ", +" :.<.[.[.[.[.[.[.[.[.[.[.[.[.[.[.[.[.}.|. 1.1.1.1.1.2.3. 1.1.1.1.1.1.1.1.1.1.1. ", +" 4.5. .= = = = = = = = = = = = = = = = = = = = = = 6.5.7. 8.= = = = = = = = = p 9. 0.= = = = = = = = = = = a. ", +" 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. ", +"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. ", +" .= 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. ", +"= = 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. ", +"= = = = = = = = = = = = = = = = = = = = = = = 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. ", +"= = = = = = = 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. ", +"= = = @+#+$+s %+| &+&+&+&+&+&+&+&+&+&+&+&+&+&+*+6 6 6 6 6 =+e.= -+B 6 6 6 6 6 ( o.&+&+&+&+&+&+&+&+&+&+&+o.( 6 6 6 6 6 I.= = a. ", +"= = ] ;+>+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. ", +"= = !.( 6 6 6 6 6 ~+{+{+{+{+{+{+{+{+{+{+{+{+{+{+]+^+/+(+@+= = = = g _+:+<+[+}+}+}+}+}+}+}+}+}+}+}+}+}+}+|+1+6 6 6 6 6 I.= = a. ", +"= = 2+( 6 6 6 6 6 3+= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = p q 6 6 6 6 6 I.= = a. ", +"= = 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. ", +"= = , 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. ", +"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. ", +" 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. ", +" n+o+= = = = = = = = = = = = = = = = = = = = = = = = = = = = b+ -.= = = = = = = = = = = a. ", +" 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+ ", +" ", +" ", +" ", +" x+y+z+ A+B+C+d+ D+E+F+G+ ", +" H+= y I+J+= K+= L+L+= y+ = = M+ = N+ = = K+ = O+ = = = = = = K+T = J+T .P+ = = = = = = = = ", +" Q+= R+ S+= T+ U+= y. = = = z+ = N+ = = = V+ = O+ = R+ M+y W+ y.= = ", +" X+= H+ = I+ K+= = = X+T = N+ = t.E+Y+ = O+ = K+ Z+= `+ F.= = ", +" t.= = @ `+= = = .@T +@ = N+ = T @@y #@ = O+ = = = = = = $@= +@ F.= = ", +" y+= = %@ O+= = = H+t.B+= N+ = T #.y+F+= O+ = T = = = Y+= U+ F.= = ", +" U+= x+ . . M+= = = L+L+= N+ = T .L+= O+ = &@ *@= y. F.= = ", +" @+ .Z+ 4 4 = X+ O+= H+ = = =@= = N+ = T +@= = O+ = L+ C+= O+ * -@ F.= = ", +" N+= = = T `+ .= = .R+ = = y+= N+ = T @+= O+ = = = = = `+ H+ .= = .;@ N+T F. ", +" ", +" ", +" ", +" ", +" ", +" ", +" "}; diff --git a/src/frontend/images/led1.gif b/src/frontend/images/led1.gif new file mode 100644 index 0000000..0d12d05 Binary files /dev/null and b/src/frontend/images/led1.gif differ diff --git a/src/frontend/images/led10.gif b/src/frontend/images/led10.gif new file mode 100644 index 0000000..608f51c Binary files /dev/null and b/src/frontend/images/led10.gif differ diff --git a/src/frontend/images/led2.gif b/src/frontend/images/led2.gif new file mode 100644 index 0000000..cdda56d Binary files /dev/null and b/src/frontend/images/led2.gif differ diff --git a/src/frontend/images/led3.gif b/src/frontend/images/led3.gif new file mode 100644 index 0000000..1bf0030 Binary files /dev/null and b/src/frontend/images/led3.gif differ diff --git a/src/frontend/images/led4.gif b/src/frontend/images/led4.gif new file mode 100644 index 0000000..683243e Binary files /dev/null and b/src/frontend/images/led4.gif differ diff --git a/src/frontend/images/led5.gif b/src/frontend/images/led5.gif new file mode 100644 index 0000000..efbb09b Binary files /dev/null and b/src/frontend/images/led5.gif differ diff --git a/src/frontend/images/led6.gif b/src/frontend/images/led6.gif new file mode 100644 index 0000000..98a8f8d Binary files /dev/null and b/src/frontend/images/led6.gif differ diff --git a/src/frontend/images/led7.gif b/src/frontend/images/led7.gif new file mode 100644 index 0000000..85cebc2 Binary files /dev/null and b/src/frontend/images/led7.gif differ diff --git a/src/frontend/images/led8.gif b/src/frontend/images/led8.gif new file mode 100644 index 0000000..1e8e1db Binary files /dev/null and b/src/frontend/images/led8.gif differ diff --git a/src/frontend/images/led9.gif b/src/frontend/images/led9.gif new file mode 100644 index 0000000..c5f9522 Binary files /dev/null and b/src/frontend/images/led9.gif differ diff --git a/src/frontend/images/leds_3.gif b/src/frontend/images/leds_3.gif new file mode 100644 index 0000000..2ff9fcd Binary files /dev/null and b/src/frontend/images/leds_3.gif differ diff --git a/src/frontend/images/leds_32.gif b/src/frontend/images/leds_32.gif new file mode 100644 index 0000000..2ff9fcd Binary files /dev/null and b/src/frontend/images/leds_32.gif differ diff --git a/src/frontend/images/loop.gif b/src/frontend/images/loop.gif new file mode 100755 index 0000000..cd13fb0 Binary files /dev/null and b/src/frontend/images/loop.gif differ diff --git a/src/frontend/images/nextcue.gif b/src/frontend/images/nextcue.gif new file mode 100755 index 0000000..497a8ed Binary files /dev/null and b/src/frontend/images/nextcue.gif differ diff --git a/src/frontend/images/play.gif b/src/frontend/images/play.gif new file mode 100755 index 0000000..b773559 Binary files /dev/null and b/src/frontend/images/play.gif differ diff --git a/src/frontend/images/prevcue.gif b/src/frontend/images/prevcue.gif new file mode 100755 index 0000000..0d553c9 Binary files /dev/null and b/src/frontend/images/prevcue.gif differ diff --git a/src/frontend/images/rec.gif b/src/frontend/images/rec.gif new file mode 100755 index 0000000..b0926f8 Binary files /dev/null and b/src/frontend/images/rec.gif differ diff --git a/src/frontend/images/rew.gif b/src/frontend/images/rew.gif new file mode 100755 index 0000000..790b225 Binary files /dev/null and b/src/frontend/images/rew.gif differ diff --git a/src/frontend/images/rewindtozero.gif b/src/frontend/images/rewindtozero.gif new file mode 100755 index 0000000..aff7b12 Binary files /dev/null and b/src/frontend/images/rewindtozero.gif differ diff --git a/src/frontend/images/stop.gif b/src/frontend/images/stop.gif new file mode 100755 index 0000000..610c64a Binary files /dev/null and b/src/frontend/images/stop.gif differ diff --git a/src/frontend/images/up.gif b/src/frontend/images/up.gif new file mode 100644 index 0000000..8af2173 Binary files /dev/null and b/src/frontend/images/up.gif differ diff --git a/src/frontend/images/wave.gif b/src/frontend/images/wave.gif new file mode 100755 index 0000000..00d9c7e Binary files /dev/null and b/src/frontend/images/wave.gif differ diff --git a/src/frontend/images/xpbutton_dn.gif b/src/frontend/images/xpbutton_dn.gif new file mode 100644 index 0000000..c3d211a Binary files /dev/null and b/src/frontend/images/xpbutton_dn.gif differ diff --git a/src/frontend/images/xpbutton_up.gif b/src/frontend/images/xpbutton_up.gif new file mode 100644 index 0000000..5248a0d Binary files /dev/null and b/src/frontend/images/xpbutton_up.gif differ diff --git a/src/frontend/images/xpbutton_uplit.gif b/src/frontend/images/xpbutton_uplit.gif new file mode 100644 index 0000000..831f171 Binary files /dev/null and b/src/frontend/images/xpbutton_uplit.gif 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 @@ +#define IDI_ICON1 101 +IDI_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 @@ +#include +hd24fs* testfs; + +void createimage_callback(void* y) +{ + cout << "." << endl; + Fl::add_timeout(1.0,createimage_callback,y); + return; +} +int passcount; +int failcount; +#define MINSECTORS 1353964 + +//#define BITBIGGER (MINSECTORS+10000) +/* this gives for a bit over 5 minutes at 48k, 24 tracks: */ +#define BITBIGGER (MINSECTORS+2073600) + +/* constant is for pretty demo image. */ +void pass() +{ + passcount++; + cout << "......................................................PASS" << endl; +} +void fail() +{ + failcount++; + cout << "......................................................FAIL" << endl; +} +void fail(const char* reason) +{ + failcount++; + cout << "......................................................FAIL" << endl; + cout << "Reason: "<c_str(),freespace2->c_str())==0) + { + fail("Images were supposed to have different sizes"); + } else { + pass(); + } + delete testfs2; + delete freespace2; + delete strtest2; +//*/ + delete freespace; + delete strtest; + return; +} + +void test_useimage() +{ + char failmsg[64]; + cout << "Try to use empty drive image... " << endl; + //false=force? + string* strtest=new string("testimage2.h24"); + testfs=new hd24fs((const char*)NULL,hd24fs::MODE_RDWR,strtest,false); + delete strtest; + strtest=NULL; + + // Let's see if all is as expected. + if (!(testfs->isOpen())) fail(); else pass(); + string* freespace=testfs->freespace(48000,24); + cout << "Free space on drive: " << *freespace << endl; + delete freespace; + hd24raw* rawfs=new hd24raw(testfs); + /* + These functions are only available through raw FS + */ + int songsondisk=rawfs->songsondisk(); + cout << "Songs on disk=" << songsondisk << endl; + if (songsondisk!=0) fail(); else pass(); + + __uint32 lastsector=rawfs->getlastsectornum(); + __uint32 expectedlastsector=BITBIGGER; + cout << "Last sectornum of drive image="<< lastsector << endl; + + + if (lastsector!=expectedlastsector) + { + sprintf(failmsg,"Expected last sector was %ld but found %ld",expectedlastsector,lastsector); + fail(failmsg); + } + else + { + pass(); + } + + string* devname=testfs->getdevicename(); + cout <<"Device name="<<*devname<volumename(); + cout <<"Volume name="<<*volname <projectcount(); + cout <<"Project count="<0) + { + currproj=testfs->getproject(0); // must error + cout << "Check protection against getting project 0" << endl; + if (currproj!=NULL) fail(); else pass(); + + delete currproj; + currproj=testfs->getproject(1); // must not error + cout << "Check zero songcount for supposedly empty project" << endl; + __uint32 songcount=currproj->songcount(); + if (songcount!=0) fail(); else pass(); + + cout << "Check getting nonexisting/invalid project numbers" << endl; + int failed=0; + for (int i=2; i<=100; i++) + { + currproj=testfs->getproject(i); // must not error but must return null + if (currproj!=NULL) + { + failed=1; + } + } + if (failed!=0) fail(); else pass(); + } + + cout << "set volume name in drive image" << endl; + testfs->setvolumename("myvol"); // only in memory!!! + // check if volume name has been set (in memory) + cout << "reading back volume name to see if set was successful" << endl; + + volname=testfs->volumename(); + if (*volname!="myvol") fail(); else pass(); + + cout << "set longer name in drive image" << endl; + testfs->setvolumename("mylongervolumename"); // only in memory!!! + volname=testfs->volumename(); + if (*volname!="mylongervolumename") fail(); else pass(); + + cout << "Test truncating too long volume name in drive image" << endl; + testfs->setvolumename("myoverlylongvolumenamethemaximumissixtyfourcharactersbutwemakeitlongeranyway"); // only in memory!!! + volname=testfs->volumename(); + if (strlen(volname->c_str())!=64) fail(); else pass(); + cout << "Try to clear volume name" <setvolumename(""); + volname=testfs->volumename(); + if (strlen(volname->c_str())!=0) fail(); else pass(); + cout << "Setting volume name " << endl; + testfs->setvolumename("MyVolume"); + cout << "and commiting for later readback." << endl; + testfs->savedriveinfo(); // auto-commit + cout << "Commit done." << endl; + return; +} + +void test_commit() +{ + string* strtest=new string("testimage2.h24"); + + cout << "Delete testfs..." << endl; + delete testfs; + testfs=NULL; + + pass(); + + testfs=new hd24fs((const char*)NULL,hd24fs::MODE_RDWR,strtest,false); + delete strtest; + cout << "Reading back volume name" << endl; + string* volname=testfs->volumename(); + cout << "Read back " << *volname << endl; + if (*volname!="MyVolume") fail(); else pass(); + + // after commit, drive size must be preserved. + hd24raw* rawfs=new hd24raw(testfs); + __uint32 lastsector=rawfs->getlastsectornum(); + __uint32 expectedlastsector=BITBIGGER; + cout << "Test if image has remained same size: "<< lastsector << endl; + if (lastsector!=expectedlastsector) fail(); else pass(); + + + testfs->setvolumename("Drive Name"); + testfs->savedriveinfo(); // commit tested before-assume it succeeds. +} + +void test_project() +{ + string* strtest=new string("testimage2.h24"); + + cout << "Delete testfs..." << endl; + delete testfs; + testfs=NULL; + + pass(); + + testfs=new hd24fs((const char*)NULL,hd24fs::MODE_RDWR,strtest,false); + delete strtest; + hd24raw* rawfs=new hd24raw(testfs); + cout << "Checking current project count... (should be 1): "; + int pcount=testfs->projectcount(); + cout << pcount << endl; + if (pcount==1) pass(); else fail("Project count of formatted drive should be 1"); + + cout << "Try to get project id 0 (should not be possible)" << endl; + hd24project* proj=testfs->getproject(0); + if (proj==NULL) pass(); else + { + delete proj; + proj=NULL; + fail("Project IDs should be 1 based but are not!"); + } + + cout << "Try to get project id 1 (first and only project on drive" << endl; + proj=testfs->getproject(1); + if (proj==NULL) fail("Cannot get only project on drive"); else + { + delete proj; + proj=NULL; + pass(); + } + cout << "Try to get any but the first project on the drive" << endl; + cout << "(using legal project numbers and one too high number)" << endl; + int projsgot=0; + int i=0; + for (i=2; i<=100; i++) + { + if (proj!=NULL) + { + delete proj; + proj=NULL; + } + proj=testfs->getproject(i); + if (proj!=NULL) + { + projsgot++; + fail("Managed to get project number:"); + cout << i << endl; + delete proj; + proj=NULL; + } + } + if (proj!=NULL) + { + delete proj; + proj=NULL; + } + + if (projsgot==0) pass(); + + cout << "Try if only project on drive is protected from deleting" << endl; + testfs->deleteproject(1); + pcount=testfs->projectcount(); + cout << pcount << endl; + if (pcount==1) pass(); else fail("Only project on drive should not be deletable"); + + cout << "Try to create a project..." << endl; + hd24project* newproj=testfs->createproject("selftest project 1"); + if (newproj==NULL) + { + fail("Creating project failed"); + } else { + pass(); + } + delete newproj; // we won't be using this object anymore. + + cout << "Make sure project creation updates project count..." << endl; + pcount=testfs->projectcount(); + if (pcount==2) pass(); else fail("Project count should have been 2 at this stage."); + cout << "Trying to delete newly created project..." << endl; + testfs->deleteproject(2); + pcount=testfs->projectcount(); + if (pcount==1) pass(); else fail("Deletion successful"); + + cout << "Trying to create 98 new projects (should be possible)..." << endl; + char projname[64]; + int failedcreate=0; + for (i=0;i<98;i++) + { + cout << "project=" << i << endl; + sprintf(projname,"selftest project %d",i+2); + hd24project* newproj=testfs->createproject(projname); + pcount=testfs->projectcount(); + if (pcount!=(i+2)) + { + sprintf(projname,"could not create project %d",i); + fail(projname); + failedcreate=1; + break; + }; + delete newproj; + } + if (failedcreate==0) + { + pass(); + } + cout << "Checking if project count is 99 as expected " << endl; + pcount=testfs->projectcount(); + if (pcount==99) pass(); else fail("Nope."); + + cout << "Trying if creating more projects than allowed is prevented" << endl; + newproj=NULL; + newproj=testfs->createproject(projname); + if (newproj!=NULL) + { + fail("Project object was returned!"); + } else { + pass(); + } + + pcount=testfs->projectcount(); + cout << "Verifying project count to still be 99" <deleteproject(50); + } + pcount=testfs->projectcount(); + if (pcount==49) pass(); else fail("Incorrect project count."); + cout << "Creating 50th project again" << i << endl; + sprintf(projname,"selftest project %d",i+2); + if (newproj!=NULL) delete newproj; + + newproj=testfs->createproject(projname); + pcount=testfs->projectcount(); + cout << "Expecting project count to be 50 now..." << endl; + if (pcount!=50) fail("Incorrect project count"); else pass(); + + cout << "Checking project sector of first project (must be 0x14 or 20)" << endl; + __uint32 projsec= rawfs->getprojectsectornum(1); + cout << "Proj sector=" << projsec << endl; + if (projsec!=0x14) fail("Incorrect sector"); else pass(); + + cout << "Deleting first project (to empty a slot)" << endl; + pcount=testfs->projectcount(); + cout << "project count BEFORE=" <deleteproject(1); + int pcount2=testfs->projectcount(); + cout << "Project count AFTER=" <getprojectsectornum(1); + cout << "Second project should originally have been on 0x15,"<createproject(projname); + pcount=testfs->projectcount(); + cout << "Expecting project count of 50 again, in reality it is " << pcount << endl; + if (pcount!=50) fail("Incorrect project count"); else pass(); + __sint32 projid=newproj->projectid(); + cout << "Project id=" << projid << endl; + if (projid!=50) { + fail("Unexpected project id"); + } + projsec=rawfs->getprojectsectornum(projid); + cout << "Expecting project sector of project " << projid << " to be 0x14," ; + cout << " in reality it is " << projsec << endl; + + if (projsec!=0x14) fail("Incorrect sector"); else pass(); + + newproj->projectname("Changed Name"); + string* projcname=newproj->projectname(); + if (*projcname!="Changed Name") fail("Project name change unsuccessful"); else pass(); + delete projcname; + newproj->save(); + delete rawfs; +} + + +void test_proj2() +{ + int pcount; + string* strtest=new string("testimage2.h24"); + + cout << "Delete testfs..." << endl; + delete testfs; + testfs=NULL; + + pass(); + + testfs=new hd24fs((const char*)NULL,hd24fs::MODE_RDWR,strtest,false); + delete strtest; + cout << "Checking current project count... (should be 50): "; + + pcount=testfs->projectcount(); + cout << "Expecting project count of 50 again, in reality it is " << pcount << endl; + if (pcount!=50) fail("Incorrect project count"); else pass(); + cout << "Getting existing project no. 50..." << endl; + hd24project* currproj=testfs->getproject(50); + if (currproj==NULL) { fail("Cannot get project"); } else {pass();} + cout << "Getting project name: "; + string* pname=currproj->projectname(); + cout << *pname << endl; + if (*pname!="Changed Name") fail("Project name change unsuccessful"); else pass(); + +// delete rawfs; + +} + +void test_song() +{ + string* strtest=new string("testimage2.h24"); + + cout << "Delete testfs..." << endl; + delete testfs; + testfs=NULL; + + pass(); + + testfs=new hd24fs((const char*)NULL,hd24fs::MODE_RDWR,strtest,false); + delete strtest; + + // Check on-disk songcount + hd24raw* rawfs=new hd24raw(testfs); + int songcount=rawfs->songsondisk(); + cout << "Checking if song count is still zero as it should be "<setvolumename("Sizeable Hard Drive"); // only in memory!!! + testfs->commit(); + + string* volname=testfs->volumename(); + if (*volname!="Sizeable Hard Drive") fail(); else pass(); + delete volname; + + cout << "Checking FS version..." << endl; + string* version=testfs->version(); + if (*version!="1.10") fail("Unexpected FS version (expectation was 1.10)"); else pass(); + delete version; + + cout << "Checking max. project count (99 expected)..." << endl; + __uint32 maxprojcount=testfs->maxprojects(); + if (maxprojcount!=99) fail("Unexpected max project count"); else pass(); + + cout << "Checking block size..." << endl; + if (testfs->getblocksizeinsectors() != 0x480) fail("Unexpected block size"); else pass(); + + // delete all but last project + while (testfs->projectcount()>1) + { + // leave only last project + testfs->deleteproject(2); + } + + // now up the total project count to 42 + char projname[64]; + int i=1; + hd24project* newproj=NULL; + while (testfs->projectcount()!=42) + { + i++; + sprintf(projname,"selftest project %d",i+2); + int prevprojcount=testfs->projectcount(); + newproj=testfs->createproject(projname); + int newprojcount=testfs->projectcount(); + if (newprojcount==prevprojcount) + { + fail("Failed to create project."); + break; + } + if (newproj!=NULL) + { + delete newproj; + newproj=NULL; + } + + } + if (newproj!=NULL) + { + delete newproj; // we won't be using this object anymore. + newproj=NULL; + } + + // rename project now. + hd24project* currproj; + currproj=testfs->getproject(15); // must error + testfs->lastprojectid(15); + currproj->projectname("Client X"); + currproj->save(); + volname=testfs->volumename(); + cout <<"Volume name="<<*volname <commit(); + delete currproj; + currproj=NULL; + currproj=testfs->getproject(15); + cout << "Test if project name change with commit works..." << endl; + cout << "Projname is supposed to be 'Client X', and is: "; + string* sprojname=currproj->projectname(); + cout << *sprojname << endl; + if (*sprojname!="Client X") fail("project name change failed."); else pass(); + delete sprojname; + cout << "Testing if song count is zero..." << endl; + if (currproj->songcount()==0) pass(); else fail("Should have been 0"); + + // Now it's time to create some songs. + for (i=0;i<12;i++) + { + hd24song* currsong=currproj->createsong("A Huge Hit",24,48000); + currsong->save(); + delete currsong; + } + currproj->lastsongid(8); + currproj->save(); + testfs->commit(); + hd24song* currsong=currproj->getsong(currproj->lastsongid()); + cout << "Renaming song..." << endl; + currsong->songname("A Huge Hit (final take)"); + currsong->save(); + testfs->commit(); + delete currsong; + currsong=NULL; + currsong=currproj->getsong(currproj->lastsongid()); + cout << "Checking if song ID is equal to last set..." << endl; + if (currsong->songid()==8) pass(); else fail("Incorrect songid."); + string* freespacebefore=testfs->freespace(48000,24); + cout << "Lengthening song..." << endl; + __uint32 desiredlen=10416000; //00:03:37.00 + __uint32 newlen=currsong->songlength_in_samples(desiredlen); + if (newlen!=desiredlen) + { + fail("Song lengthening failed."); + cout << "Length in samples is " << newlen + << "instead of " << desiredlen << endl; + } else pass(); + + currsong->setwriteprotected(true); + currsong->save(); + testfs->commit(); + cout << "Free space on drive before lengthening: " << *freespacebefore << endl; + string* freespace=testfs->freespace(48000,24); + cout << "Free space on drive after lengthening: " << *freespace << endl; + delete freespace; +} + +int runselftest(HD24UserInterface* ui) +{ + cout << "=======TESTMODE ACTIVATED=======" << endl; + passcount=0; + failcount=0; + test_createimage(); + test_useimage(); + test_commit(); + test_project(); + test_proj2(); + + test_song(); + test_demoimage(); // create an interesting looking demo drive image + + + cout << "Create 1 project, 99 projects, try 100th project" << endl; + + cout << "Create 1..99 songs" << endl; + + cout << "rename projects, rename songs" << endl; + + cout << "Delete 1.99 projects/songs" << endl; + + cout << "Record audio to songs" << endl; + + // Proceed to test gui. + + Fl_Window* window=ui->make_window(testfs); + window->end(); + window->show(); + fl_message("Proceeding to test GUI."); + cout << "====================== TEST COMPLETE ===================" << endl; + cout << "PASS: " << passcount << endl; + cout << "FAIL: " << failcount << endl; + cout << "========================================================" << endl; + return 0; +} 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 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0109 +header_name {.h} +code_name {.cxx} +decl {class HD24TrackChannel;} {public +} + +decl {class TrackInfo;} {public +} + +decl {class HD24UserInterface;} {public +} + +decl {class MixerUI;} {public +} + +decl {class RecorderUI;} {public +} + +decl {class PortAudioWrapper;} {public +} + +decl {class JackWrapper;} {public +} + +decl {class hd24transferengine;} {public +} + +decl {\#define HD24DEBUG 0} {public +} + +decl {\#define BLINKRATE 25} {public +} + +decl {\#define PA_FRAMESPERBUF 512} {public +} + +decl {\#define MAXCHANNELS 24} {public +} + +decl {\#define UIREFRESH 1 /* 1=best, 10=1/10 refresh rate */} {public +} + +decl {\#define HD24MODE hd24fs::MODE_RDWR} {public +} + +decl {\#define TIMEOUT 0.03} {public +} + +decl {\#define SPLITFILESIZE_BYTES ((__uint64)(1024*1024*1024))} {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include /* portaudio, libjack */} {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {class HD24UserInterface;} {public +} + +decl {class HD24control;} {public +} + +decl {class SoundFileWrapper;} {public +} + +class HD24data {} { + decl {HD24UserInterface* parentui;} {} + decl {friend class HD24control;} {} + decl {int ready;} {public + } +} + +class HD24control {} { + decl {HD24data* data;} {} + Function {parentui(HD24UserInterface* p_parentui)} {open + } { + code {data->parentui=p_parentui;} {} + } + Function {parentui()} {open return_type {HD24UserInterface*} + } { + code {return data->parentui;} {} + } + Function {HD24control()} {open + } { + code {data=new HD24data();} {} + } + Function {~HD24control()} {open + } { + code {delete data;} {} + } + Function {ready()} {open return_type int + } { + code {return data->ready;} {} + } + Function {ready(int p_ready)} {open return_type void + } { + code {data->ready=p_ready;} {} + } +} + +decl {\#include } {public +} + +class HD24UserInterface {open +} { + decl {hd24transferengine* transeng;} {} + decl {HD24control* control;} {public + } + decl {PortAudioWrapper* portaudio;} {public + } + decl {SoundFileWrapper* soundfile;} {public + } + decl {JackWrapper* libjack;} {public + } + decl {int busy;} {public + } + decl {hd24fs* defaulthd24;} {} + decl {hd24fs* currenthd24;} {public + } + decl {int trackselected[24];} {public + } + decl {hd24project* currproj;} {public + } + decl {hd24song* currsong;} {public + } + decl {Fl_Check_Button* track[24];} {public + } + decl {int tracksave[24]; /* to keep track[24] settings */} {public + } + decl {vector format_outputextension;} {public + } + decl {vector format_shortdesc;} {public + } + Function {deactivate_ui()} {open return_type void + } { + code {drivename->deactivate(); +rename_drive->deactivate(); +projectname->deactivate(); +rename_project->deactivate(); +songname->deactivate(); +songinfogroup->deactivate(); +tabDrive->deactivate(); +rename_song->deactivate(); +locatepoints->deactivate(); +fromto->deactivate(); +transfercanvas->deactivate(); +menufile->deactivate(); +tabRecorder->deactivate(); +tabMixer->deactivate(); +menuhelp->deactivate();} {} + } + Function {disable_program_controls()} {return_type void + } { + code {drivename->deactivate(); +rename_drive->deactivate(); +projectname->deactivate(); +rename_project->deactivate(); +songname->deactivate(); +rename_song->deactivate(); +transfercanvas->deactivate(); +locatepoints->deactivate(); +fromto->deactivate(); +button_golocatepoint->deactivate(); +recorder->control->disable();} {} + } + Function {activate_ui()} {open return_type void + } { + code {drivename->activate(); +transfercanvas->activate(); +tabRecorder->activate(); +projectname->activate(); +songname->activate(); +songinfogroup->activate(); +tabDrive->activate(); +tabMixer->activate(); +locatepoints->activate(); +fromto->activate(); +menufile->activate(); +menuhelp->activate();} {} + } + Function {addsongtodropdown(int i)} {} { + code {\#if (HD24DEBUG==1) + cout << "addsongtodropdown " << i << endl; + cout << "set song" << endl; +\#endif + hd24song* song=currproj->getsong(i); +\#if (HD24DEBUG==1) + cout << "song is set" << endl; +\#endif + string* strsongname=Convert::int2str(i); + *strsongname+=": "; + string* actualname=song->songname(); + *strsongname+=*actualname; + delete actualname; + +\#if (HD24DEBUG==1) + cout << "song is set2" << endl; +\#endif + songname->add(strsongname->c_str(),0,(void (*)(Fl_Widget*,void*))(&(songname_cb)),(void*)this); +\#if (HD24DEBUG==1) + cout << "song is set3" << endl; +\#endif + delete song; + delete(strsongname);} {} + } + Function {populate_projectlist(int projectid)} {return_type void + } { + code {/* Set project info */ +int i; +\#if (HD24DEBUG==1) + cout << "clear project list" << endl; +\#endif +for (i=0;i<=100;i++) { + projectname->remove(0); +} +int numprojs=0; +if (currenthd24==NULL) { + return; +} +numprojs=currenthd24->projectcount(); +for (i=1; i<=numprojs; i++) { + hd24project* currproj=currenthd24->getproject(i); + string* projname1=Convert::int2str(i); + *projname1+=": "; + string* currpname=currproj->projectname(); + *projname1+=*currpname; + projectname->add(projname1->c_str(),0,(void (*)(Fl_Widget*,void*))(&(projectname_cb)),(void*)this); + delete(currpname); + delete(projname1); + delete currproj; +} + +select_project(projectid);} {} + } + Function {populate_songlist(int songid)} {open return_type void + } { + code {int i; +int numsongs=currproj->songcount(); +\#if (HD24DEBUG==1) + cout << "populate_songlist" << endl; +\#endif +if (numsongs==0) +{ +\#if (HD24DEBUG==1) + cout << "no songs" << endl; +\#endif + for (i=0;i<=100;i++) { + songname->remove(0); + } + songname->add("-- Empty project --",0,NULL,(void*)this); + songname->value(0); + refresh(songname); + return; +} +songname->activate(); +\#if (HD24DEBUG==1) + cout << "clear songlist" << endl; +\#endif +for (i=0;i<=100;i++) { + songname->remove(0); +} + +songname->add("-- All songs --",0,(void (*)(Fl_Widget*,void*))(&(songname_cb)),(void*)this); + +\#if (HD24DEBUG==1) + cout << "Add songs to dropdown" << endl; +\#endif +for (i=1; i<=numsongs; i++) { + addsongtodropdown(i); +} +control->ready(1); +this->busy=0; + +\#if (HD24DEBUG==1) + cout << "about to select last used song" << endl; +\#endif +signed long lastsong=currproj->lastsongid(); +if (lastsong<1) { + lastsong=0; +} +\#if (HD24DEBUG==1) + cout << "got last song id:" << lastsong << endl; +\#endif +if (lastsong==0) { + songname->value(0); + songname->redraw(); + return; +} +select_song(lastsong); +songname->redraw();} {} + } + Function {populate_drivelist(int driveid)} {open return_type void + } { + code {// when another drive has been selected, init dropdown lists. +for (unsigned int q=0;q<=99;q++) { + drivename->remove(0); +} +// find out how many ADAT drives are detected. +unsigned int devcount=defaulthd24->hd24devicecount(); +\#if (HD24DEBUG==1) + cout << "devcount=" << devcount << endl; +\#endif +unsigned int usedevcount=devcount; +if (devcount==0) usedevcount=1; // we are using a file image. +for (unsigned int devnum=0;devnumc_str(),defaulthd24->mode(),devnum); + delete idir; + if (!(currhd24->isOpen())) { + if (!(defaulthd24->isOpen())) { + disable_program_controls(); + } + } +\#if (HD24DEBUG==1) +cout << "newfs" << devnum << endl; +\#endif + + string* drivename1=Convert::int2str(devnum+1); + + *drivename1+=": "; + string* volname; + +\#if (HD24DEBUG==1) +cout << "getvolname" << devnum << endl; +\#endif + + if (devcount!=usedevcount) + { + volname=currenthd24->volumename(); + } else { + volname=currhd24->volumename(); + } + +\#if (HD24DEBUG==1) +cout << "gotvolname" << devnum << endl; +\#endif + + *drivename1+=*volname; + // NULL=callback + drivename->add(drivename1->c_str(),0,(void (*)(Fl_Widget*,void*))(&(drivename_cb)),(void*)this); + delete(currhd24); + delete(volname); + delete(drivename1); +} + +/* Set drive info */ +\#if (HD24DEBUG==1) +cout << "set drivename dropdown value to " << driveid << endl; +\#endif +drivename->value(driveid);} {} + } + Function {populate_locatepoints(hd24song* locsong,Fl_Choice* lpoints)} {open return_type int + } { + code {int i; +int numpoints=0; +if (locsong!=NULL) +{ + numpoints=locsong->locatepointcount(); +} + +\#if (HD24DEBUG==1) + cout << "populate_lpoints" << endl; +\#endif +if (numpoints==0) +{ +\#if (HD24DEBUG==1) + cout << "no locate points." << endl; +\#endif + for (i=0;i<=99;i++) { + lpoints->remove(0); + } + lpoints->deactivate(); + refresh(lpoints); + return numpoints; +} +lpoints->activate(); +\#if (HD24DEBUG==1) + cout << "clear lpoints" << endl; +\#endif +for (i=0;i<=99;i++) { + lpoints->remove(0); +} +for (i=0; igetlocatepos(i); +\#if (HD24DEBUG==1) + cout << "locate pos "<getlocatename(i); + + if ((locname1->length())>0) { + while (locname1->substr(0,1)==" ") { + *locname1=locname1->substr(1,locname1->length()-1); + } + while (locname1->substr(locname1->length()-1,1)==" ") { + *locname1=locname1->substr(0,locname1->length()-1); + } + } else { + *locname1+="START"; + } + *locname1+=": "; + if (i==numpoints) { + *locname1+="+"; + } + string* dur=locsong->display_duration(locatepos); + *locname1+=*dur; + delete (dur); + } else { + locname1=Convert::int2str(i,2,"0"); + *locname1+=": +"; + string* dur=locsong->display_duration(locatepos); + *locname1+=*dur; + delete (dur); + *locname1+=" "; + string* lni=locsong->getlocatename(i); + *locname1+=*lni; + delete(lni); + } + +\#if (HD24DEBUG==1) + cout << "add lpoints" << endl; +\#endif + lpoints->add(locname1->c_str(),0,NULL,(void*)this); + delete locname1; + lpoints->redraw(); +\#if (HD24DEBUG==1) + cout << "added lpoints" << endl; +\#endif +} + +button_setlocatepoint->activate(); +lpoints->value(0); +this->setlocbuttonlabel(0); +return numpoints;} {} + } + Function {init_vars()} {open return_type void + } { + code {\#if (HD24DEBUG == 1) +cout << "init_vars" << endl; +\#endif +//jackclient=NULL; +//jackmtsample=NULL; +currsong=NULL; +currproj=NULL; +//portaudiostream=NULL; +//inputParameters=new PaStreamParameters; +//outputParameters=new PaStreamParameters; +//portaudiooffset=0; +//pa_streamtime=0; +//portaudio_initialized=0; +//portaudio_mustloop=0; +//portaudio_looppos=0; +mustdisplaytimer=true; +mustdispsavemessage=false; +closingdown=false; +savemessage[0]='\\0'; +refreshingui=0; +//loopmode=0; +//dispwritecountdown=0; +init_gui(0); +Fl::add_timeout(TIMEOUT,poll_callback,this);} {} + } + Function {ui_refresh(const char* orig)} {open + } { + code {/* to prevent re-refresh by selecting current project + which will select a song which will refresh the current + ui again...(in case of corrupt 'unexpected end of song' + songs): */ +if (refreshingui>1) return; +refreshingui++; + +// init dropdown lists. +\#if (HD24DEBUG==1) +cout << "==TRIGGER GUI REFRESH FROM "<remove(0); + songname->remove(0); +} +int devid=0; +if ((currenthd24!=NULL)&&(currenthd24!=defaulthd24)) +{ + devid=currenthd24->getdeviceid(); + if (devid<0) + { + devid=0; + } +} +\#if (HD24DEBUG==1) +cout << "going to populate drive list (" << devid << ")" << endl; +\#endif + +populate_drivelist(devid); + +// following uses fsys (the default drive) +\#if (HD24DEBUG==1) +cout << "get projcount then?" << endl; +\#endif +string* nump=Convert::int2str(currenthd24->projectcount()); +\#if (HD24DEBUG==1) +cout << "got projcount=" << *nump << endl; +\#endif +number_of_projects->value(nump->c_str()); +delete (nump); +\#if (HD24DEBUG==1) +cout << "last project id=" << currenthd24->lastprojectid() << endl; +\#endif + +populate_projectlist(currenthd24->lastprojectid()); + + +string* cat=new string(""); +if (hd24utils::gencatalog(this->currenthd24,cat)==0) { + this->catalogbuffer->remove(0,this->catalogbuffer->length()-1); + this->catalogbuffer->append(cat->c_str()); + +// if (this->catalog->buffer()!=NULL) { +// free(this->catalog->buffer()); +// } +// this->catalog->buffer(cat->c_str()); +} +delete(cat); +\#if (HD24DEBUG==1) +cout << "get version" << endl; +\#endif +string* version1=currenthd24->version(); +\#if (HD24DEBUG==1) +cout << "got version" << endl; +\#endif +fsversion->value(version1->c_str()); +delete(version1); + +calcspace(); +Fl::add_timeout(TIMEOUT,poll_callback,this); + +refreshingui--;} {} + } + Function {init_gui(int drive)} {open return_type void + } { + code {// int drive is for multi drive support. + +// deselect all tracks on ' copy to hd24 tab' +for (unsigned int i=1; i<=MAXCHANNELS; i++) { + trackselected[i-1]=0; +} +// Neither jack or portaudio were found by configure. +// This means no sound is available, so hide the transport controls. +recorder->control->disable(); +recorder->control->audio->mixer(this->mixer->control); + +\#if (HD24DEBUG==1) + cout << "init_gui" << endl; +\#endif +Fl::remove_timeout(poll_callback); +ui_refresh("init gui"); +Fl::add_timeout(TIMEOUT,poll_callback,this); + +populate_formats(); +\#if (HD24DEBUG==1) + cout << "formats populated" << endl; +\#endif +fromtime->value("START"); +totime->value("END"); +refresh(fromtime); +refresh(totime); +\#if (HD24DEBUG==1) + cout << "init gui complete" << endl; +\#endif + +calcspace(); +showprogtitle(); + + +setstatus("Ready.");} {} + } + Function {drivename_cb(Fl_Widget* w, void* data)} {return_type {static void} + } { + code {\#if (HD24DEBUG==1) + cout << "drivename_cb" << endl; +\#endif +HD24UserInterface *o=(HD24UserInterface *)data; +o->drivename_callback(w,data);} {} + } + Function {drivename_callback(Fl_Widget* w, void* data)} {return_type void + } { + code {\#if (HD24DEBUG==1) + cout << "drivename_callback" << endl; +\#endif +int choicemade=((Fl_Choice*)(w))->value(); +\#if (HD24DEBUG==1) +cout << "chose drive " << choicemade+1 << endl; +\#endif + + +string* idir=hd24utils::getlastdir("driveimagedir"); +hd24fs* newcurrenthd=new hd24fs(idir->c_str(),defaulthd24->mode(),choicemade); +delete idir; +currenthd24=newcurrenthd; + +init_gui(choicemade);} {} + } + Function {trackaction_callback(Fl_Widget* w, void* data)} {return_type void + } { + code {\#if (HD24DEBUG==1) + cout << "trackaction_callback" << endl; +\#endif +int choicemade=((Fl_Choice*)(w))->value(); +if (choicemade==0) { + ((Fl_Choice*)(w))->color(1); +} else { + ((Fl_Choice*)(w))->color(7); +} +\#if (HD24DEBUG==1) +cout << "chose item " << choicemade << endl; +\#endif} {} + } + Function {projectname_cb(Fl_Widget* w, void* data)} {return_type {static void} + } { + code {\#if (HD24DEBUG==1) + cout << "projectname_cb" << endl; +\#endif +HD24UserInterface *o=(HD24UserInterface *)data; +o->projectname_callback(w,data);} {} + } + Function {projectname_callback(Fl_Widget* w, void* data)} {return_type void + } { + code {\#if (HD24DEBUG==1) + cout << "projectname_callback" << endl; +\#endif +int choicemade=((Fl_Choice*)(w))->value(); +select_project(choicemade+1);} {} + } + Function {songname_cb(Fl_Widget* w, void* data)} {open return_type {static void} + } { + code {\#if (HD24DEBUG == 1 ) + cout << "songname_cb" << endl; +\#endif +HD24UserInterface *o=(HD24UserInterface *)data; +o->songname_callback(w,data);} {} + } + Function {songname_callback(Fl_Widget* w, void* data)} {open return_type void + } { + code {\#if (HD24DEBUG==1) + cout << "songname_callback" << endl; +\#endif +int choicemade=((Fl_Choice*)(w))->value(); +if (currproj!=NULL) delete currproj; +currproj=currenthd24->getproject(projectname->value()+1); +//songname->value(choicemade); // should not be needed +select_song(choicemade); // song id=choicemade} {} + } + Function {refresh(Fl_Widget * w)} {open return_type void + } { + code {w->deactivate(); +w->activate();} {} + } + decl {time_t starttime,endtime} {} + Function {calcspace()} {return_type void + } { + code {__uint32 rate; +__uint32 tracks; + +switch (atrate->value()) { + case 0: rate=44100; break; + case 1: rate=48000; break; + case 2: rate=88200; break; + case 3: rate=96000; break; + default: return; +} +switch (attracks->value()) { + case 0: tracks=2; break; + case 1: tracks=6; break; + case 2: tracks=8; break; + case 3: tracks=12; break; + case 4: tracks=16; break; + case 5: tracks=24; break; + default: return; +} +string* strfree=currenthd24->freespace(rate,tracks); +freespace->value(strfree->c_str()); +delete (strfree);} {} + } + Function {transferstatus(void* ui,const char* message,double pct)} {open return_type {static void} + } { + code {if (ui==NULL) return; +((HD24UserInterface*)ui)->statusmsg->value(message); +((HD24UserInterface*)ui)->fl_check();} {} + } + Function {setstatus(string message)} {open return_type void + } { + code {statusmsg->value(message.c_str()); +fl_check();} {} + } + decl {/* ===File transfer stuff ===================================================== */} {} + decl {Fl_Widget* trackaction[24];} {public + } + decl {int transfer_cancel;} {public + } + decl {Fl_Output* filename[24];} {public + } + Function {savemessage_callback(void* user)} {open return_type {static void} + } { + code {HD24UserInterface* mythis=(HD24UserInterface*)user; +string* stat=new string(mythis->savemessage); +mythis->setstatus(*stat); +//mythis->uicanvas->redraw(); +mythis->statusbar->damage(); +mythis->statusbar->redraw(); + +delete (stat); +if (mythis->mustdispsavemessage) { +Fl::repeat_timeout(.25,savemessage_callback,user); +}} {} + } + Function {countfiletracks(const char* filename)} {open return_type int + } { + code {SF_INFO sfinfo; +SNDFILE* infile=NULL; +if (strlen(filename)==0) +{ + return 0; +} +infile=soundfile->sf_open(filename,SFM_READ,&sfinfo); +if (!infile) +{ + return 0; +} +int numchans=sfinfo.channels; +soundfile->sf_close(infile); +return numchans;} {} + } + decl {char savemessage[300];} {public + } + Function {populate_trackaction(HD24UserInterface* ui,Fl_Widget* o,int tracknum)} {open return_type void + } { + code {if (tracknum<1) { +return; +} +if (tracknum>24) { + return; +} + +trackaction[tracknum-1]=o; + +((Fl_Choice*)o)->clear(); +((Fl_Choice*)o)->add("Erase",0,(void (*)(Fl_Widget*,void*))(&(trackaction_cb)),(void*)this); +((Fl_Choice*)o)->add("SMPTE",0,(void (*)(Fl_Widget*,void*))(&(trackaction_cb)),(void*)this); +((Fl_Choice*)o)->add("Mono",0,(void (*)(Fl_Widget*,void*))(&(trackaction_cb)),(void*)this); +// count number of tracks in file given by filename +// when >1, for each track add a line. +int numtracks=countfiletracks(filename[tracknum-1]->value()); +if (numtracks>1) { + for (int i=1; i<=numtracks; i++) { + string strtrack="Tr."; + string* strnum=Convert::int2str(i); + strtrack+=*strnum; + ((Fl_Choice*)o)->add(strtrack.c_str(),0,(void (*)(Fl_Widget*,void*))(&(trackaction_cb)),(void*)this); + delete strnum; + } +} +((Fl_Choice*)o)->value(2); // default 0=erase, 1=SMPTE, 2=mono +((Fl_Choice*)o)->redraw(); +fl_check();} {} + } + Function {populate_trackactionbyfile(__uint32 slotnum,int trackchoice)} {open return_type void + } { + code {if (slotnum<0) return; +if (slotnum>23) return; + +Fl_Choice* o=(Fl_Choice*)trackaction[slotnum]; +if (o==NULL) return; +for (unsigned int i=0;i<128;i++) { o->remove(0); } +o->add("Erase",0,(void (*)(Fl_Widget*,void*))(&(trackaction_cb)),(void*)this); +o->add("SMPTE",0,(void (*)(Fl_Widget*,void*))(&(trackaction_cb)),(void*)this); +o->add("Mono",0,(void (*)(Fl_Widget*,void*))(&(trackaction_cb)),(void*)this); +// count number of tracks in file given by filename +// when >1, for each track add a line. +int numtracks=countfiletracks(filename[slotnum]->value()); +if (numtracks>1) { + for (int i=1; i<=numtracks; i++) { + string strtrack="Tr."; + string* strnum=Convert::int2str(i); + strtrack+=*strnum; + o->add(strtrack.c_str(),0,(void (*)(Fl_Widget*,void*))(&(trackaction_cb)),(void*)this); + delete strnum; + } +} +o->value(trackchoice); +trackaction_callback(o,NULL); +o->redraw(); + +fl_check();} {} + } + Function {moveselected(__sint32 direction)} {open return_type void + } { + code {__uint32 firsttrack=0; +__uint32 lasttrack=0; +if (currsong==NULL) +{ + return; +} +if (direction==-1) +{ + firsttrack=1; + lasttrack=currsong->logical_channels(); + if (trackselected[0]==1) + { + // move up, but first track is selected + // and already upper choice- cannot move up + return; + } +} +else +{ + if (direction==1) + { + lasttrack=1; + firsttrack=currsong->logical_channels(); + + if (trackselected[currsong->logical_channels()-1]==1) + { + return; + } + } +} +// we need to move stuff. +if (firsttrack==0) return; // direction==0, don't move. + +__uint32 tracknum=firsttrack; +while (tracknum!=lasttrack) +{ + if (trackselected[tracknum-1]!=trackselected[tracknum-1-direction]) + { + int dummy=trackselected[tracknum-1]; + string* trackval=new string(filename[tracknum-1]->value()); + + trackselected[tracknum-1]=trackselected[tracknum-1-direction]; + trackselected[tracknum-1-direction]=dummy; + + int a=((Fl_Choice*)(trackaction[tracknum-1]))->value(); + int b=((Fl_Choice*)(trackaction[tracknum-1-direction]))->value(); + + filename[tracknum-1]->value(filename[tracknum-1-direction]->value()); + filename[tracknum-1-direction]->value(trackval->c_str()); + + populate_trackactionbyfile(tracknum-1,b); + populate_trackactionbyfile(tracknum-1-direction,a); + + delete trackval; + } + tracknum-=direction; +} + +redrawtracks();} {} + } + Function {trackaction_cb(Fl_Widget* w, void* data)} {open return_type {static void} + } { + code {\#if (HD24DEBUG==1) + cout << "trackaction_cb" << endl; +\#endif +HD24UserInterface *o=(HD24UserInterface *)data; +o->trackaction_callback(w,data);} {} + } + Function {redrawtracks()} {open return_type void + } { + code {bool track_active; +if (currsong==NULL) { + return; +} + +for (unsigned int tracknum=1;tracknum<=MAXCHANNELS;tracknum++) +{ + if (currsong->logical_channels()>=tracknum) { + track_active=true; + filename[tracknum-1]->activate(); + } else { + track_active=false; + ((Fl_Output*)filename[tracknum-1])->color(7); + filename[tracknum-1]->deactivate(); + } + + if (track_active) { + if (trackselected[tracknum-1]==1) { + ((Fl_Output*)filename[tracknum-1])->color(3); + } else { + ((Fl_Output*)filename[tracknum-1])->color(7); + } + } + + ((Fl_Output*)filename[tracknum-1])->redraw(); +}} {} + } + decl {/* ===UI stuff ===================================================== */} {} + Function {populate_formats()} {open return_type void + } { + code {\#if (HD24DEBUG==1) + cout << "populate_formats" << endl; +\#endif + +for (int i=0;isupportedformatcount();i++) +{ + fileformat->add(transeng->getformatdesc(i),0,NULL,(void*)this); +} +fileformat->value(0);} {} + } + Function {selectfilename(int tracknum)} {return_type void + } { + code {this->trackselected[tracknum-1]=1-this->trackselected[tracknum-1]; +if (this->trackselected[tracknum-1]==1) { + this->filename[tracknum-1]->color(3); +} else { + this->filename[tracknum-1]->color(7); +} +this->filename[tracknum-1]->redraw();} {} + } + Function {select_project(int projectid)} {open return_type void + } { + code {if (currproj!=NULL) { + if (currsong!=NULL) + { + hd24song* tmpsong=currsong; + currsong=NULL; + delete tmpsong; + } + hd24project* tmpproj=currproj; + currproj=NULL; + delete tmpproj; +} +currproj=currenthd24->getproject(projectid); +\#if (HD24DEBUG==1) + cout << "select_project \#" << projectid << endl; +\#endif +currenthd24->lastprojectid(projectid); +projectname->value(projectid-1); /* project id is 1-based */ +int currsongcount=0; +if (currproj==NULL) +{ + delete_project->deactivate(); +} +else +{ + delete_project->activate(); + currsongcount=currproj->songcount(); +} + +if (currsongcount==0) +{ + number_of_songs->value("0"); + populate_songlist(0); // shows -- EMPTY PROJECT -- + select_song(0); + return; +} + +// currproj is defined at this point. + +string* nums=Convert::int2str(currproj->songcount()); +number_of_songs->value(nums->c_str()); +\#if (HD24DEBUG==1) + cout << "number of songs=" << currproj->songcount() << endl; +\#endif +delete(nums); + +int lastsongid=currproj->lastsongid(); +\#if (HD24DEBUG==1) + cout << "lastsongid=" << lastsongid << endl; +\#endif +populate_songlist(lastsongid);} {} + } + Function {select_song(int songid)} {open return_type void + } { + code {unsigned int i; +button_setlocatepoint->deactivate(); +\#if (HD24DEBUG==1) +cout << "select_song \#" << songid << endl; +\#endif + + + +if (songid==0) { + + // This represents the choice "all songs" + if (currsong!=NULL) { + hd24song* tmpsong=currsong; + currsong=NULL; + delete tmpsong; + } + transfersource->value("(All songs in the current project)"); + if (number_of_tracks==NULL) + { + return; // ui not yet initialized? + } + tab_tohd24->deactivate(); + rename_song->deactivate(); + delete_song->deactivate(); + number_of_tracks->value(""); + number_of_tracks->deactivate(); + sample_rate->value(""); + sample_rate->deactivate(); + bitdepth->value(""); + bitdepth->deactivate(); + duration->value(""); + duration->deactivate(); + //refresh (songname); + for (i=0; ideactivate(); + track[i]->value(1); + track[i]->show(); + } + button_setlocatepoint->deactivate(); + button_golocatepoint->deactivate(); + button_invert_tracks->deactivate(); + choice_startloc=0; // use default + // disable locatepoint dropdown: + choice_endloc=populate_locatepoints(currsong,locatepoints); + choice_endloc=0; + update_fromto(); + fromto->deactivate(); + refresh (tab_tohd24); + return; + +} else { +\#if (HD24DEBUG==1) +cout << "activate buttons" << endl; +\#endif + delete_song->activate(); + rename_song->activate(); + tab_tohd24->activate(); + button_golocatepoint->activate(); + button_setlocatepoint->activate(); + button_invert_tracks->activate(); + rename_song->activate(); + sample_rate->activate(); + bitdepth->activate(); + duration->activate(); + refresh (rename_song); + refresh (number_of_tracks); + refresh (sample_rate); + refresh (bitdepth); + refresh (duration); + refresh (tab_tohd24); +\#if (HD24DEBUG==1) +cout << "deselect old song" << endl; +\#endif + if (currsong!=NULL) { + recorder->control->song(NULL); /* tell recorder that the song is gone */ + delete currsong; + currsong=NULL; + } +\#if (HD24DEBUG==1) +cout << "currprojgetsong" << endl; +\#endif + currsong=currproj->getsong(songid); + currproj->lastsongid(songid); + if (currsong->has_unexpected_end()) { + if (currsong->is_fixable_unexpected_end()) { + song_messages->value("Unexpected end of song.\\nTrying to find the rest of the audio..."); +// currenthd24->dumpclusterusage2(currenthd24->findorphanclusters()); + unsigned char* orphans=currenthd24->findorphanclusters(); + if (orphans != NULL) { + currsong->appendorphanclusters(orphans,true /*allowsongresize*/); + song_messages->value( + "Unexpected end of song. I think I found back the rest of it.\\n" + "However, you really should backup all audio and reformat this drive."); + if (currenthd24->getmaintenancemode()==1) { + if (confirm("Song was recovered. Do you wish to save the changes?\\nAnswer Yes only if you have verified that the audio is OK)")) { + currsong->save(); + } + } + } + } + else + { + ui_refresh("selectsong"); + song_messages->value("Unexpected end of song.\\nHD24tools can not automatically fix this specific occurence."); + } + } else { + song_messages->value("No messages."); + } +} + + +\#if (HD24DEBUG==1) +cout << "songname->value" << endl; +\#endif + +songname->value(songid); // entry 0=all songs, 1=song id 1 +string* dummy=currsong->songname(); +transfersource->value(dummy->c_str()); + +/* This should al be done by the recorder.... +string disp="S"; +string* idstr=Convert::int2str(songid,2,"0"); +disp+=*idstr; +delete idstr; +disp+=":\\""; +string* dummy=currsong->songname(); +transfersource->value(dummy->c_str()); +string* dummy2=Convert::readstring((unsigned char*)dummy->c_str(),0,10); +string* dummy3=Convert::readstring((unsigned char*)dummy->c_str(),0,11); + +disp+=*dummy2; +delete dummy; +delete dummy2; +if (dummy3->length()>10) +{ +disp+="\\4"; // arrow right +} else { +disp+="\\""; +} +delete dummy3; +string* disp2=Convert::padright(disp,16," "); + +string* dur=currsong->display_duration(); + +*disp2+=dur->substr(0,8); +*disp2+=":"; +*disp2+=dur->substr(9,2); +*disp2+=" "; +if (currsong->iswriteprotected()) +{ +*disp2+="\\1"; +} else { +*disp2+="\\2"; +} +string* strtracksb=Convert::int2str(currsong->logical_channels(),2,"0"); +*disp2+=*strtracksb; +delete strtracksb; +*disp2+="t"; + +recorder->control->dispwrite(0,disp2->c_str()); +delete disp2; + ............. until this point */ +recorder->control->song(currsong); /* load song into recorder */ + +redrawtracks(); // enable/disable tracks for export to HD24 +string* strtracks=Convert::int2str(currsong->logical_channels()); +number_of_tracks->value(strtracks->c_str()); +number_of_tracks->activate(); +delete (strtracks); +string* samrat=Convert::int2str(currsong->samplerate()); +sample_rate->value(samrat->c_str()); +sample_rate->activate(); +delete samrat; +if (mixer!=NULL) { + mixer->control->samplerate(this->samplerate()); +} + +string* bitd=Convert::int2str(currsong->bitdepth()); +bitdepth->value(bitd->c_str()); +bitdepth->activate(); +delete(bitd); + +string* dur=currsong->display_duration(); +duration->value(dur->c_str()); +duration->activate(); +delete(dur); + +if (currsong->iswriteprotected()) { + writeprotected->value(1); +} else { + writeprotected->value(0); +} + +refresh (songname); +refresh (number_of_tracks); +refresh (sample_rate); +refresh (bitdepth); +refresh (duration); +refresh (writeprotected);// writeprotected->deactivate(); + +for (i=0; ilogical_channels();i++) { + track[i]->activate(); + track[i]->show(); + trackled[i]->show(); +} +for (i=currsong->logical_channels();ideactivate(); + track[i]->hide(); + trackled[i]->hide(); +} + +choice_startloc=0; // use default +choice_endloc=populate_locatepoints(currsong,locatepoints); +button_golocatepoint->activate(); +if (choice_endloc>0) { + fromto->activate(); +} +update_fromto();} {} + } + decl {int choice_startloc;} {} + decl {int choice_endloc;} {} + decl {bool mustdispsavemessage;} {public + } + decl {int loopmode;} {public + } + decl {int uiredrawcount; /* to limit refreshing UI */} {public + } + Function {update_fromto()} {return_type void + } { + code {if (currsong==NULL) +{ +fromtime->value("START"); +totime->value("END"); +return; +} +string* dummy1=currsong->getlocatename(choice_startloc); +string* dummy2=currsong->getlocatename(choice_endloc); +string* strfrom=Convert::trim(dummy1); +string* strto=Convert::trim(dummy2); + + +fromtime->value(strfrom->c_str()); +totime->value(strto->c_str()); +delete(dummy1); +delete(dummy2); +delete (strfrom); +delete (strto);} {} + } + Function {make_window(hd24fs* p_fsys) /* <------------------------------------------- */} {open + } { + Fl_Window {} { + label HD24connect open + xywh {485 44 605 530} type Double color 52 align 5 + code0 {defaulthd24=p_fsys;} + code1 {currenthd24=p_fsys; // current and default to allow multi drive support} + code2 {init_vars();} visible + } { + Fl_Group {} {open + xywh {-5 0 1720 540} + } { + Fl_Group menucanvas {open + xywh {0 0 640 24} + } { + Fl_Menu_Bar {} {open + xywh {0 0 640 24} color 52 + } { + Submenu menufile { + label {&File} open + xywh {0 0 100 20} labelsize 12 + } { + MenuItem {} { + label {&Detect HD24 drives} + callback {if (currenthd24!=NULL) { + delete currenthd24; + currenthd24=NULL; +} + +string* idir=hd24utils::getlastdir("driveimagedir"); +currenthd24=new hd24fs(idir->c_str(),hd24fs::MODE_RDWR); +delete idir; +defaulthd24=currenthd24; +if (!(currenthd24->isOpen())) +{ + 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."); +} +ui_restart();} + xywh {0 0 34 21} labelsize 12 divider + } + MenuItem {} { + label {&Open drive image...} + callback {string* driveimgdir=hd24utils::getlastdir("driveimagedir"); + +Fl_Native_File_Chooser chooser; +chooser.directory(driveimgdir->c_str()); +delete driveimgdir; +chooser.title("Select HD24 drive image\\0"); +chooser.type(Fl_Native_File_Chooser::BROWSE_FILE); +chooser.filter("Drive Images\\t*.{img,bin,h24,hd24}\\0"); +//chooser.preview(0); +switch (chooser.show()) { + case -1: break; //error + case 1: break; //cancel + default: + if (chooser.filename()) { + string* cfilename=new string(chooser.filename()); + + //cout << "filename = " << *strfile << endl; + string* fpath=new string(""); + *fpath+=cfilename->substr(0,strlen(cfilename->c_str())-strlen(fl_filename_name(cfilename->c_str()))); + hd24utils::setlastdir("driveimagedir",fpath->c_str()); + + hd24fs* sysob=new hd24fs(fpath->c_str(),hd24fs::MODE_RDWR,cfilename,false); + delete cfilename; + if (currenthd24!=NULL) + { + currenthd24->~hd24fs(); + } + if (defaulthd24!=NULL) + { + if (defaulthd24!=currenthd24) + { + defaulthd24->~hd24fs(); + } + } + currenthd24=sysob; + defaulthd24=sysob; + + if (!(currenthd24->isOpen())) + { + bool choice=confirm( + "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." + ); + + if (choice) { + if (sysob!=NULL) { + delete (sysob); + } + bool wantheader=confirm("Do you want to load a header file?"); + + cfilename=new string(chooser.filename()); + string* idir=hd24utils::getlastdir("driveimagedir"); + sysob=new hd24fs(idir->c_str(),hd24fs::MODE_RDWR,cfilename,true); //force + delete idir; + delete cfilename; + if (currenthd24!=NULL) + { + currenthd24->~hd24fs(); + } + if (defaulthd24!=NULL) + { + if (defaulthd24!=currenthd24) + { + defaulthd24->~hd24fs(); + } + + } + + currenthd24=sysob; + defaulthd24=sysob; + if (currenthd24->isOpen()) { + if (wantheader) { + loadheaderfile(); + } + ui_restart(); + return; + } + fl_message("Cannot open HD24 device image."); + } + + return; + } + ui_restart(); + } + break; +}} + xywh {0 0 34 21} labelsize 12 + } + MenuItem {} { + label {&Save drive image...} + callback {string* driveimgdir=new string(""); +*driveimgdir+=*hd24utils::getlastdir("driveimagedir"); + +Fl_Native_File_Chooser chooser; +chooser.filter("Drive Images\\t*.{img,bin,h24,hd24}\\0"); +chooser.title("Export full drive image file"); +chooser.directory(driveimgdir->c_str()); +chooser.options(Fl_Native_File_Chooser::NEW_FOLDER); +chooser.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); + +switch (chooser.show()) { + case -1: break; //error + case 1: break; //cancel + default: + // save header to chooser.filename() + + bool bFileexists=hd24utils::fileExists(chooser.filename()); + if (bFileexists) { + bool choice=confirm( + "A file with this name already exists. Do you wish to overwrite it?" + ); + if (!(choice)) return; + } + string* strfile=new string(chooser.filename()); + //cout << "filename = " << *strfile << endl; + string* fpath=new string(""); + *fpath+=strfile->substr(0,strlen(strfile->c_str())-strlen(fl_filename_name(strfile->c_str()))); + hd24utils::setlastdir("driveimagedir",fpath->c_str()); + this->transfer_cancel=0; + this->mustdispsavemessage=true; + Fl::add_timeout(.25,savemessage_callback,this); + int result=hd24utils::savedriveimage(currenthd24,strfile,&this->savemessage[0],&this->transfer_cancel); + delete strfile; + if (result==0) { + fl_message("Drive image created successfully."); + setstatus("Done."); + } else { + fl_message("Could not write drive image to file. Access denied? Disk full?"); + } + this->mustdispsavemessage=false; + break; +} +delete driveimgdir;} + xywh {10 10 34 21} labelsize 12 + } + Submenu {} { + label {&Catalog} open + xywh {0 0 70 21} labelsize 12 + } { + MenuItem {} { + label {&Export catalog...} + callback {string* catdir=new string(""); +*catdir+=*hd24utils::getlastdir("catalogdir"); + +Fl_Native_File_Chooser chooser; +chooser.filter("Text files\\t*.txt"); +chooser.title("Export disk catalog to file"); +chooser.directory(catdir->c_str()); +chooser.options(Fl_Native_File_Chooser::NEW_FOLDER); +chooser.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); + +switch (chooser.show()) { + case -1: break; //error + case 1: break; //cancel + default: + // save header to chooser.filename() + + bool bFileexists=hd24utils::fileExists(chooser.filename()); + if (bFileexists) { + bool choice=confirm( + "A file with this name already exists. Do you wish to overwrite it?" + ); + if (!(choice)) return; + } + string* strfile=new string(chooser.filename()); + //cout << "filename = " << *strfile << endl; + string* fpath=new string(""); + *fpath+=strfile->substr(0,strlen(strfile->c_str())-strlen(fl_filename_name(strfile->c_str()))); + hd24utils::setlastdir("catalogdir",fpath->c_str()); + string* anyerrors=hd24utils::savecatalog(currenthd24,strfile); + delete strfile; + if (anyerrors==NULL) { + fl_message("Catalog file created successfully."); + } else { + delete anyerrors; + fl_message("Could not write catalog file. Access denied? Disk full?"); + } + break; +} +delete catdir;} + tooltip {Save the disk directory to a printable text file} xywh {40 40 34 21} labelsize 12 + } + MenuItem {} { + label {&Print catalog} + callback {string* result=hd24utils::printcatalog(currenthd24); +if (result!=NULL) +{ + if (strlen(result->c_str())!=0) + { + fl_message("%s",result->c_str()); + } +} +delete result;} + tooltip {Save the disk directory to a printable text file} xywh {30 30 34 21} labelsize 12 divider + } + } + Submenu {} { + label {&Mixer} open + xywh {10 10 70 21} labelsize 12 + } { + MenuItem {} { + label {&Save mixer settings to file,,,} + callback {mixer->savetofile();} + tooltip {Save the current mixer settings to a file} xywh {50 50 34 21} labelsize 12 + } + MenuItem {} { + label {&Load mixer settings from file...} + callback {mixer->loadfromfile();} + tooltip {Recall mixer settings from a previously saved mix} xywh {60 60 34 21} labelsize 12 divider + } + MenuItem {} { + label {&Save mixer settings to HD24 drive,,,} + tooltip {Save the current mix onto the HD24 drive} xywh {60 60 34 21} labelsize 12 deactivate + } + MenuItem {} { + label {&Load mixer settings from HD24 drive...} + tooltip {Recall mixer settings from a mix previously saved to the current HD24 drive} xywh {70 70 34 21} labelsize 12 deactivate + } + } + Submenu {} { + label {&Recovery} open + xywh {0 0 70 21} labelsize 12 divider + } { + MenuItem {} { + label {&Select device...} + callback {dialog_choosedevice* chooser=new dialog_choosedevice(); +Fl_Double_Window* w=chooser->make_window(currenthd24); +w->end(); +w->show(); +while (w->visible()) { +Fl::wait(); +} +string* cfilename; +hd24fs* sysob; +string* idir=NULL; +switch (chooser->buttonclicked) { + case 1: + // OK + cfilename=new string(chooser->devicename->c_str()); + idir=hd24utils::getlastdir("driveimagedir"); + sysob=new hd24fs(idir->c_str(),hd24fs::MODE_RDWR,cfilename,false); + delete idir; idir=NULL; + + currenthd24=sysob; + defaulthd24=sysob; + + if (!(currenthd24->isOpen())) + { + bool choice=confirm( + "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." + ); + + if (choice) { + if (sysob!=NULL) { + delete (sysob); + } + string* idir=hd24utils::getlastdir("driveimagedir"); + sysob=new hd24fs(idir->c_str(),hd24fs::MODE_RDWR,cfilename,true); //force + delete idir; + currenthd24=sysob; + defaulthd24=sysob; + int tryheader=0; + if (currenthd24->isOpen()) { + tryheader=1; + bool wantheader=confirm("Do you want to load a header file?"); + if (wantheader) { + loadheaderfile(); + } + + ui_restart(); + delete cfilename; + return; + } + if (tryheader==1) { + fl_message("Cannot open HD24 device."); + } else { + fl_message("Cannot open HD24 device. Access denied?"); + } + } + delete cfilename; + break; + } + ui_restart(); + delete cfilename; + break; + case 2: + // cancel + break; + default: + // unknown + break; +} +delete chooser;} + xywh {5 5 34 21} labelsize 12 + } + MenuItem {} { + label {Load &header file...} + callback {loadheaderfile();} + xywh {5 5 34 21} labelsize 12 + } + MenuItem {} { + label {&Create header file...} + callback {string* headerdir=new string(""); +*headerdir+=*hd24utils::getlastdir("headerdir"); + +Fl_Native_File_Chooser chooser; +chooser.filter("Header files (*.h24)\\t"); +chooser.title("Create header file"); +chooser.options(Fl_Native_File_Chooser::NEW_FOLDER); +chooser.directory(headerdir->c_str()); +chooser.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); + +switch (chooser.show()) { + case -1: break; //error + case 1: break; //cancel + default: + // save header to chooser.filename() + bool bFileexists=hd24utils::fileExists(chooser.filename()); + if (bFileexists) { + bool choice=confirm( + "A file with this name already exists. Do you wish to overwrite it?" + ); + if (!(choice)) return; + } + string* strfile=new string(chooser.filename()); + string* fpath=new string(""); + *fpath+=strfile->substr(0,strlen(strfile->c_str())-strlen(fl_filename_name(strfile->c_str()))); + hd24utils::setlastdir("headerdir",fpath->c_str()); + + int result=hd24utils::saveheader(currenthd24,strfile); + delete strfile; + if (result==0) { + fl_message("Header file created successfully."); + } else { + fl_message("Could not write header file. Access denied? Disk full?"); + } + break; +}} + xywh {15 15 34 21} labelsize 12 + } + MenuItem {} { + label {Recover song from &power failure} + callback {if (currsong==NULL) { + fl_message("First select the song to recover."); + return; +} + +dialog_setlength* ui_setlength; +ui_setlength=new dialog_setlength; +int currlocchoice=locatepoints->value(); +Fl_Window *win=ui_setlength->make_window(currsong,currlocchoice); +win->end(); +win->show(); + +while (win->visible()) { Fl::wait(); } + +if (ui_setlength->buttonclicked==1) { + // TODO: + // - create header file + // getuserdatapath. + // + + char userdatapath[FL_PATH_MAX]; + Fl_Preferences* prefs=new Fl_Preferences(Fl_Preferences::USER,"HD24","HD24connect"); + prefs->getUserdataPath(userdatapath,FL_PATH_MAX); + delete prefs; + string* headerfilename=new string(userdatapath); + + // add OS directory slash if forgotten +\#ifdef WINDOWS +\#define OSSLASH '\\\\' +\#else +\#define OSSLASH '/' +\#endif +const char* x=headerfilename->c_str(); +int q=strlen(x); +if (q>0) +{ + if (x[q-1]!=OSSLASH) + { + *headerfilename+=OSSLASH; + } +} +*headerfilename+="livefix.h24"; + + int createtempheaderresult=hd24utils::savedrivesectors(currenthd24,headerfilename,0,0x10c76,NULL,NULL); + + if (createtempheaderresult!=0) + { + delete headerfilename; + fl_message("Couldn't create a temporary header file, cannot continue. Sorry."); + return; + } + // header was created successfully. + currenthd24->useheaderfile(*headerfilename); + //cout << "Userdatapath="<songlength_in_samples(ui_setlength->locpoint,clearnew); + currsong->save(); + ui_refresh("liverec"); +} +delete ui_setlength;} + xywh {10 10 36 21} labelsize 12 + } + } + MenuItem {} { + label {E&xit} + callback {/* Find current window */ +this->finish(); + +Fl_Window * x=Fl::first_window(); +x->~Fl_Window(); +delete x; +x=NULL;} + xywh {0 0 100 20} labelsize 12 + } + } + Submenu menutools { + label {&Tools} open + xywh {10 10 100 20} labelsize 12 + } { + Submenu {} { + label {Alter &order of songs in project} open + xywh {20 20 100 20} labelsize 12 divider + } { + MenuItem {} { + label {Sort &Alphabetically} + callback {if (this->currproj==NULL) +{ + fl_message("Cannot sort project- no project selected."); + return; +} +this->currproj->sort(); +this->currproj->save(); +this->ui_refresh("sort");} + xywh {30 30 34 21} labelsize 12 + } + } + MenuItem {} { + label {&Options...} + callback {dialog_options* ui_options; +ui_options=new dialog_options; +Fl_Window *win=ui_options->make_window(); +win->end(); +win->show(); + +while (win->visible()) { Fl::wait(); } + +delete ui_options;} + xywh {30 30 34 21} labelsize 12 + } + } + Submenu menuhelp { + label {&Help} open + xywh {0 0 100 20} labelsize 12 + } { + MenuItem {} { + label {&About} + callback {UserInterface_HelpAbout* ui_help_about; +ui_help_about=new UserInterface_HelpAbout; + +Fl_Window *helpaboutdialog=ui_help_about->make_window(); +helpaboutdialog->end(); +helpaboutdialog->show(); + +while (helpaboutdialog->visible()) { Fl::wait(); }} + xywh {0 0 100 20} labelsize 12 + } + MenuItem {} { + label {System &Info} + callback {string info="HD24connect system info\\n"; +info+="JACK: "; +if (libjack->libloaded) { + info+="Loaded"; +} else { + info+="Not present"; +} +info+="\\n"; + +info+="LIBSNDFILE: "; +if (soundfile->libloaded) { + info+="Loaded"; +} else { + info+="Not present"; +} +info+="\\n"; + + +info+="PORTAUDIO: "; +if (portaudio->libloaded) { + info+="Loaded"; +} else { + info+="Not present"; +} +info+="\\n"; + + +fl_message("%s",info.c_str());} + xywh {20 20 100 20} labelsize 12 + } + MenuItem {} { + label {Report a &Bug} + callback {string bug="No warranty of any kind is given on this program.\\n\\n"; +bug+="However, if you find any defects or faults in it, they\\n"; +bug+="will most likely be fixed with high priority in the next\\n"; +bug+="release, as long as the author is aware of them.\\n\\n"; +bug+="Should you find any defects, please email the author at\\n"; +bug+="the following e-mail address:\\n\\n"; +bug+="mrjb@@dnd.utwente.nl.\\n\\n"; +bug+="Make sure to include 'hd24' in the subject line."; +fl_message("%s",bug.c_str());} + xywh {0 0 100 20} labelsize 12 + } + MenuItem {} { + label {Request a &Feature} + callback {string bug="If you would like a specific feature to be added, please\\n"; +bug+="please email your request to the author at the following \\n"; +bug+="e-mail address:\\n\\n"; +bug+="mrjb@@dnd.utwente.nl.\\n\\n"; +bug+="Make sure to include 'hd24 feature request' in the subject line.\\n"; +bug+="You can increase the priority of the request by donating."; +fl_message("%s",bug.c_str());} + xywh {10 10 100 20} labelsize 12 + } + MenuItem {} { + label {&Credits} + callback {string thanks="Extra Special thanks go out to: \\n\\n"; +thanks+="Randy Bryant for trusting me to use his Mac\\n"; +thanks+="Mike Crute for hosting and builder support\\n"; +thanks+="Cabbage for building various Mac package installers\\n"; +thanks+="Edward van Westerlaak for Windows and Mac/OSX beta testing, hardware support and suggestions\\n"; +thanks+="Erik de Castro Lopo and other contributors for libsndfile\\n"; +thanks+="Ross Bencina, Phil Burk, Bjorn Roche and other contributors for the portaudio library\\n"; +thanks+="Bill Spitzak and others for the Fast Light Toolkit\\n"; +thanks+="Sveinn Kjartansson for providing the means for high sample rate support\\n\\n"; +thanks+="Special thanks go out to the Yahoo Groups HD24 community\\n"; +thanks+="for additional beta testing, suggestions and general encouragement.\\n\\n"; +fl_message("%s",thanks.c_str());} + xywh {10 10 100 20} labelsize 12 + } + } + } + } + Fl_Group uicanvas {open + xywh {-5 0 1720 540} resizable + } { + Fl_Group transfercanvas { + label Transfer + xywh {10 360 590 150} box UP_BOX color 52 labelfont 1 labelsize 12 align 5 + } {} + Fl_Group statusbar { + xywh {-5 510 725 20} box DOWN_BOX color 23 + } { + Fl_Output backgroundbox { + xywh {0 510 605 20} color 52 labelsize 12 textsize 12 + } + Fl_Button stop_transfer { + label Cancel + callback {transfer_cancel=1; +stop_transfer->hide();} + xywh {525 510 80 20} labelsize 12 align 16 + code0 {o->hide();} + } + Fl_Output statusmsg { + xywh {0 510 525 20} color 52 labelsize 12 textsize 12 + } + } + Fl_Tabs Tabs { + callback {this->readmixer(); +this->mixer->damage(); +if (o->value()==tabRecorder) +{ + if (recorder->button_play->value()==0) + { + showprogtitle(); + } +}} open + xywh {-5 25 1600 485} + code0 {o->value(tabDrive);} + } { + Fl_Group tabDrive { + label Drive open + xywh {0 45 605 465} box UP_BOX color 52 labelfont 1 labelsize 12 align 5 hide + } { + Fl_Choice drivename { + label {Drive name:} + xywh {155 80 440 20} down_box BORDER_BOX labelsize 12 textsize 12 + } {} + Fl_Output fsversion { + label {FS version:} + xywh {305 105 50 20} labelsize 12 textsize 12 + code0 {o->clear_visible_focus();} + } + Fl_Output number_of_projects { + label {Number of projects:} + xywh {155 105 70 20} labelsize 12 textsize 12 + code0 {o->clear_visible_focus();} + } + Fl_Button rename_drive { + label {Rename...} + callback {if (currenthd24==NULL) return; +dialog_rename* ui_rename; +ui_rename=new dialog_rename(); +string* currname=currenthd24->volumename(); +string* strname=new string("Rename project"); +Fl_Window* win=ui_rename->make_window(currname,strname); +if (strname!=NULL) +{ + delete strname; +} +if (currname!=NULL) +{ + delete currname; +} +win->end(); +win->show(); + +while (win->visible()) { Fl::wait(); } +if (ui_rename->buttonclicked==1) +{ + // OK clicked + if (confirm("Do you wish to write the changes to disk?")) { + currenthd24->setvolumename(*(ui_rename->itemname)); + currenthd24->savedriveinfo(); + populate_drivelist(1+drivename->value()); + drivename->redraw(); + } +} +delete ui_rename; +ui_refresh("ren proj");} + xywh {510 105 85 20} labelsize 12 align 16 + } + Fl_Output freespace { + label {Free space preview:} + xywh {155 130 140 20} labelsize 12 textsize 12 + code0 {o->clear_visible_focus();} + } + Fl_Choice atrate { + label {at } + callback {calcspace();} open + xywh {320 130 85 20} down_box BORDER_BOX labelsize 12 textsize 12 + code0 {o->value(0);} + } { + MenuItem {} { + label 44100 + xywh {5 5 100 20} value 1 labelsize 12 + } + MenuItem {} { + label 48000 + xywh {15 15 100 20} value 1 labelsize 12 + } + MenuItem {} { + label 88200 + xywh {25 25 100 20} value 1 labelsize 12 + } + MenuItem {} { + label 96000 + xywh {35 35 100 20} value 1 labelsize 12 + } + } + Fl_Choice attracks { + label {Hz, } + callback {calcspace();} open + xywh {435 130 75 20} down_box BORDER_BOX labelsize 12 textsize 12 + code0 {o->value(5);} + } { + MenuItem {} { + label 2 + xywh {15 15 100 20} value 1 labelsize 12 + } + MenuItem {} { + label 6 + xywh {25 25 100 20} value 1 labelsize 12 + } + MenuItem {} { + label 8 + xywh {35 35 100 20} value 1 labelsize 12 + } + MenuItem {} { + label 12 + xywh {45 45 100 20} value 1 labelsize 12 + } + MenuItem {} { + label 16 + xywh {55 55 100 20} value 1 labelsize 12 + } + MenuItem {} { + label 24 + xywh {65 65 100 20} value 1 labelsize 12 + } + } + Fl_Box {} { + label tracks + xywh {510 130 55 20} labelsize 12 align 20 + } + Fl_Group {} {open + xywh {25 70 15 15} + } {} + Fl_Box {} { + label {Drive information} + xywh {0 58 5 17} labelfont 1 labelsize 12 align 8 + } + Fl_Text_Display catalog { + label {Drive contents} + xywh {5 190 595 310} box DOWN_BOX labelfont 1 labelsize 12 align 5 textfont 4 textsize 12 + code0 {if (catalogbuffer==NULL) catalogbuffer=new Fl_Text_Buffer(); string* cat=new string("\\n"); catalogbuffer->append(cat->c_str()); delete cat;} + code1 {o->buffer(catalogbuffer); o->scrollbar_align(FL_ALIGN_RIGHT);} + } + Fl_Button format_driveimage { + label Format + 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"); +if (!wantformat) return; +// Okay, user is absolutely sure. +currenthd24->write_enable(); +currenthd24->quickformat(NULL); +// there's no point in re-enabling write +// protection again now, is there? +ui_refresh("format"); +setstatus("Format complete."); +return;} + xywh {455 105 55 20} labelsize 12 align 16 + } + Fl_Button create_driveimage { + label {New Image...} + callback {dialog_filesize* ui_filesize; +ui_filesize=new dialog_filesize(); +Fl_Window *win=ui_filesize->make_window(); +win->end(); +win->show(); + +while (win->visible()) { Fl::wait(); } +__uint32 lastsector=0; + +if (ui_filesize->buttonclicked!=1) +{ + delete ui_filesize; + return; +} + +lastsector=ui_filesize->lastsector; +delete ui_filesize; + +string* driveimgdir=new string(""); +*driveimgdir+=*hd24utils::getlastdir("driveimagedir"); + +Fl_Native_File_Chooser chooser; +chooser.filter("Drive Images\\t*.{img,bin,h24,hd24}\\0"); +chooser.title("Create empty drive image in file"); +chooser.directory(driveimgdir->c_str()); +chooser.options(Fl_Native_File_Chooser::NEW_FOLDER); +chooser.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); + +switch (chooser.show()) { + case -1: break; //error + case 1: break; //cancel + default: + // save header to chooser.filename() + + bool bFileexists=hd24utils::fileExists(chooser.filename()); + if (bFileexists) { + bool choice=confirm( + "A file with this name already exists. Do you wish to overwrite it?" + ); + if (!(choice)) return; + } + string* strfile=new string(chooser.filename()); + //cout << "filename = " << *strfile << endl; + string* fpath=new string(""); + *fpath+=strfile->substr(0,strlen(strfile->c_str())-strlen(fl_filename_name(strfile->c_str()))); + hd24utils::setlastdir("driveimagedir",fpath->c_str()); + this->transfer_cancel=0; + this->mustdispsavemessage=true; + Fl::add_timeout(.25,savemessage_callback,this); +// __uint32 lastsector=2097151; // 1 GiB + int result=hd24utils::newdriveimage(strfile,lastsector,&this->savemessage[0],&this->transfer_cancel); + + this->mustdispsavemessage=false; + setstatus("Done."); + if (result==0) { + setstatus("Done."); + int wantopen=confirm("Drive image created successfully.\\nDo you want to open it now?"); + if (wantopen==1) + { + string* idir=hd24utils::getlastdir("driveimagedir"); + hd24fs* sysob=new hd24fs(idir->c_str(),hd24fs::MODE_RDWR,strfile,false); + delete idir; + if (currenthd24!=NULL) + { + currenthd24->~hd24fs(); + } + if (defaulthd24!=NULL) + { + if (defaulthd24!=currenthd24) + { + defaulthd24->~hd24fs(); + } + + } + currenthd24=sysob; + defaulthd24=sysob; + } + + } else { + fl_message("Could not write drive image to file. Access denied? Disk full?"); + } + delete strfile; + break; +} +setstatus("Done."); +ui_refresh("newdriveimage"); +delete driveimgdir;} + xywh {360 105 95 20} labelsize 12 align 16 + } + Fl_Box {} { + label {Songs marked * are write-protected.} + xywh {235 175 365 15} labelfont 2 labelsize 12 align 24 + } + } + Fl_Group songinfogroup { + label {Project/Song} + xywh {0 50 605 460} box UP_BOX color 52 labelfont 1 labelsize 12 align 5 hide + } { + Fl_Choice songname { + label {Song name:} open + xywh {155 155 440 20} down_box BORDER_BOX labelsize 12 textsize 12 + } {} + Fl_Output number_of_tracks { + label {Number of tracks:} + xywh {155 180 90 20} labelsize 12 textsize 12 + code0 {o->clear_visible_focus();} + } + Fl_Output sample_rate { + label {Sample rate:} + callback {if (currsong==NULL) return; +bool confirmrate=false; +if (strcmp(o->value(),"44100")==0) { + o->value("48000"); + currsong->samplerate(48000); + if (mixer!=NULL) mixer->control->samplerate(48000); + confirmrate=confirm("Re-stamp song as 48000Hz on disk?"); +} else { + if (strcmp(o->value(),"48000")==0) { + o->value("44100"); + currsong->samplerate(44100); + if (mixer!=NULL) mixer->control->samplerate(44100); + confirmrate=confirm("Re-stamp song as 44100Hz on disk?"); + } +} +if (strcmp(o->value(),"88200")==0) { + o->value("96000"); + currsong->samplerate(96000); + if (mixer!=NULL) mixer->control->samplerate(48000); + confirmrate=confirm("Re-stamp song as 96000Hz on disk?"); +} else { + if (strcmp(o->value(),"96000")==0) { + o->value("88200"); + if (mixer!=NULL) mixer->control->samplerate(44100); + confirmrate=confirm("Re-stamp song as 88200Hz on disk?"); + } +} + + if (confirmrate) { +// currsong->songname(*(ui_rename->itemname)); + currsong->save(); + populate_songlist(songname->value()); + } else { + + + +if (strcmp(o->value(),"44100")==0) { + o->value("48000"); + currsong->samplerate(48000); + if (mixer!=NULL) mixer->control->samplerate(48000); +} else { + if (strcmp(o->value(),"48000")==0) { + o->value("44100"); + currsong->samplerate(44100); + if (mixer!=NULL) mixer->control->samplerate(44100); + } +} +if (strcmp(o->value(),"88200")==0) { + o->value("96000"); + currsong->samplerate(96000); + if (mixer!=NULL) mixer->control->samplerate(48000); +} else { + if (strcmp(o->value(),"96000")==0) { + o->value("88200"); + currsong->samplerate(88200); + if (mixer!=NULL) mixer->control->samplerate(44100); + } +} + + + } +ui_refresh("stamprate");} + xywh {155 230 90 20} labelsize 12 textsize 12 + code0 {o->clear_visible_focus();} + } + Fl_Output bitdepth { + label {Bit depth:} + xywh {155 255 90 20} labelsize 12 textsize 12 + code0 {o->clear_visible_focus();} + } + Fl_Output duration { + label {Duration:} + xywh {155 205 90 20} labelsize 12 textsize 12 + code0 {o->clear_visible_focus();} + } + Fl_Button rename_song { + label {Rename...} + callback {if (currsong==NULL) return; +dialog_rename* ui_rename; +ui_rename=new dialog_rename(); +string* currname=currsong->songname(); +string* strsong=new string("Rename song"); +Fl_Window* win=ui_rename->make_window(currname,strsong); +delete strsong; +win->end(); +win->show(); + +while (win->visible()) { Fl::wait(); } +if (ui_rename->buttonclicked==1) +{ + // OK clicked + if (confirm("Do you wish to write the changes to disk?")) { + currsong->songname(*(ui_rename->itemname)); + currsong->save(); + populate_songlist(songname->value()); + } +} + +delete ui_rename; +ui_refresh("rename song");} + xywh {510 180 85 20} labelsize 12 align 16 + } + Fl_Choice locatepoints { + label {Locate points:} + callback {setlocbuttonlabel(locatepoints->value()); +if ((locatepoints->value())==25) { +button_setlocatepoint->deactivate(); +} else { +button_setlocatepoint->activate(); +}} open + xywh {155 280 215 20} down_box BORDER_BOX labelsize 12 textsize 12 deactivate + } {} + Fl_Button button_setlocatepoint { + label {Edit...} + callback {if (currsong==NULL) return; +dialog_setlocate* ui_setlocate; +ui_setlocate=new dialog_setlocate; +int currlocchoice=locatepoints->value(); +Fl_Window *win=ui_setlocate->make_window(currsong,locatepoints->value()); +win->end(); +win->show(); + +while (win->visible()) { Fl::wait(); } + +/* Dialog has closed, read the results */ + +populate_locatepoints(currsong,locatepoints); +locatepoints->value(currlocchoice); + +if (ui_setlocate->useasrange==1) { + if (currlocchoice==1) + { + choice_startloc=1; + } + if (currlocchoice==2) + { + choice_endloc=2; + } +} +currsong->save(); + +update_fromto(); +delete ui_setlocate;} + xywh {370 280 60 20} labelsize 12 align 16 deactivate + } + Fl_Check_Button writeprotected { + label {Write protected} + callback {if (currsong==NULL) return; +bool confirmprot=false; +if (o->value()==0) { + currsong->setwriteprotected(false); + confirmprot=confirm("Write-enable song on disk?"); +} else { + if (o->value()==1) { + currsong->setwriteprotected(true); + confirmprot=confirm("Write-protect song on disk?"); + } +} + +if (confirmprot) { + currsong->save(); + populate_songlist(songname->value()); +} else { + if (o->value()==0) { + o->value(1); + } else { + o->value(0); + } +} +ui_refresh("writeprot");} + xywh {155 300 20 25} down_box DOWN_BOX labelsize 12 align 8 + } + Fl_Button button_golocatepoint { + label Go + callback {if (currsong==NULL) return; +if (recorder==NULL) return; +recorder->control->hd24_transport_goloc(currsong->getlocatepos(locatepoints->value()));} + xywh {435 280 155 20} labelsize 12 align 16 + } + Fl_Output number_of_songs { + label {Number of songs:} + xywh {155 105 85 20} labelsize 12 textsize 12 + code0 {o->clear_visible_focus();} + } + Fl_Choice projectname { + label {Project name:} open + xywh {155 80 440 20} down_box BORDER_BOX labelsize 12 textsize 12 + } {} + Fl_Button rename_project { + label {Rename...} + callback {if (currproj==NULL) return; +dialog_rename* ui_rename; +ui_rename=new dialog_rename(); + +string* currname=currproj->projectname(); +string* strproject=new string("Rename project"); +Fl_Window* win=ui_rename->make_window(currname,strproject); +if (strproject!=NULL) +{ + delete strproject; +} +win->end(); +win->show(); + +while (win->visible()) { Fl::wait(); } +if (ui_rename->buttonclicked==1) +{ + // OK clicked + if (confirm("Do you wish to write the changes to disk?")) { + currproj->projectname(*(ui_rename->itemname)); + currproj->save(); + populate_projectlist(1+projectname->value()); + } + + + + +} +delete ui_rename; +ui_refresh("ren proj 2");} + xywh {510 105 85 20} labelsize 12 align 16 + } + Fl_Box {} { + label {Project information} + xywh {0 58 5 17} labelfont 1 labelsize 12 align 8 + } + Fl_Box {} { + label {Song information} + xywh {0 138 5 17} labelfont 1 labelsize 12 align 8 + } + Fl_Output song_messages_label { + label {Recovery messages:} + xywh {155 325 10 20} type Multiline labelsize 12 textsize 12 + code0 {o->clear_visible_focus();} + } + Fl_Output song_messages { + xywh {155 325 440 40} type Multiline labelsize 12 textsize 12 + code0 {o->clear_visible_focus();} + } + Fl_Button delete_project { + label Delete + 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!"); +if (!wantdel) return; +__sint32 projtodel=currproj->projectid(); +__uint32 result=currenthd24->deleteproject(projtodel); +result++; result--; // ignore for now +ui_refresh("del proj");} + xywh {455 105 55 20} labelsize 12 align 16 + } + Fl_Button delete_song { + label Delete + callback {if (currproj==NULL) return; +if (currsong==NULL) return; + +bool wantdel=confirm("Are you sure you want to delete this song and its recorded audio?\\nThis operation cannot be undone!"); +if (!wantdel) return; +__uint32 songtodel=currsong->songid(); +__uint32 result=currproj->deletesong(songtodel); +result++; result--; //ignore for now +ui_refresh("del song");} + xywh {455 180 55 20} labelsize 12 align 16 + } + Fl_Button create_project { + label {New Project...} + callback {if (currenthd24==NULL) { + fl_message("No drive is currently selected."); + return; +} + +if (currenthd24->projectcount() == currenthd24->maxprojects()) +{ + fl_message("Cannot create project.\\nThe maximum number of projects is already in use!"); + return; +} +// - check if current project is NULL +// - check if there's song space left in it +dialog_newproject* ui_newproject; +ui_newproject=new dialog_newproject(); +Fl_Window *win=ui_newproject->make_window(); +win->end(); +win->show(); + +while (win->visible()) { Fl::wait(); } + +if (ui_newproject->buttonclicked!=1) +{ + delete ui_newproject; + return; +} +char projname[65]; +for (int i=0;i<65;i++) { + projname[i]=0; +} +hd24project* newproj=currenthd24->createproject( +(const char*)strncpy(projname,ui_newproject->projectname,64) +); +if (newproj==NULL) +{ + fl_message("Could not create the project. Access denied?"); + delete ui_newproject; + return; +} + +//if (ui_newsong->buttonclicked==1) { +// lastsector=ui_filesize->lastsector; +//} +ui_refresh("createproj"); +delete ui_newproject;} + xywh {360 105 95 20} labelsize 12 align 16 + } + Fl_Button create_song { + label {New Song...} + callback {if (currenthd24==NULL) { + fl_message("No drive is currently selected."); + return; +} + +if (currproj==NULL) { + fl_message("No project is currently selected."); + return; +} + +if (currproj->songcount() == currproj->maxsongs()) +{ + fl_message("Cannot create song.\\nThe maximum number of songs is already in use!"); + return; +} +savemessage[0]='\\0'; +transfer_cancel=0; + +this->mustdispsavemessage=true; +Fl::add_timeout(0,savemessage_callback,this); + +dialog_newsong* ui_newsong; +ui_newsong=new dialog_newsong(); +Fl_Window *win=ui_newsong->make_window(); +win->end(); +win->show(); + + + +while (win->visible()) { Fl::wait(); } + + + +//__uint32 lastsector=0; + +if (ui_newsong->buttonclicked!=1) +{ + mustdispsavemessage=false; + transfer_cancel=1; + delete ui_newsong; + return; +} + +char songname[65]; +for (int i=0;i<65;i++) { + songname[i]=0; +} +hd24song* newsong=currproj->createsong( +(const char*)strncpy(songname,ui_newsong->songname,64),ui_newsong->trackcount,ui_newsong->samplerate +); + + +if (newsong==NULL) +{ + fl_message("Could not create the song. Access denied?"); + mustdispsavemessage=false; + transfer_cancel=1; + delete ui_newsong; + return; +} +__uint32 samlen=ui_newsong->songlength_in_samples; +win->~Fl_Window(); +delete ui_newsong; +// optionally, lengthen song to specified size. +if (samlen>0) { + setstatus("Lengthening song... "); + + +\#if (HD24DEBUG==1) + cout << "about to start lengthening song to maxlen=" << samlen << endl; +\#endif + bool clearnew=true; // clear lengthened part + + __uint32 translen=newsong->songlength_in_samples(samlen,clearnew,&this->savemessage[0],&this->transfer_cancel,Fl::check); + + +\#if (HD24DEBUG==1) + cout << "verifying actual song length " << endl; + cout << "new len=" << translen << endl; +\#endif + if (translen!=samlen) + { +\#if (HD24DEBUG==1) + + cout << "new len<> maxlen so not enough space." << endl; +\#endif + if (transfer_cancel==0) + { + fl_message("Not enough space on HD24 drive."); + } else + { + fl_message("Song lengthening cancelled by user."); + } + return; + } + newsong->save(); + +\#if (HD24DEBUG==1) +cout << "translen is now " << translen << endl; +\#endif +} +stop_transfer->hide(); +this->mustdispsavemessage=false; +delete newsong; // ui refresh will pick it up as currsong. +ui_refresh("newsong"); +setstatus("Ready."); +return;} + xywh {360 180 95 20} labelsize 12 align 16 + } + Fl_Box {} { + label Hz + xywh {245 230 19 20} labelsize 12 align 20 + } + Fl_Box {} { + label {hours:minutes:seconds.frames} + xywh {245 205 195 20} labelsize 12 align 20 + } + } + Fl_Group tabRecorder { + label Recorder open + xywh {-5 46 620 464} color 52 labelfont 1 labelsize 12 hide + } { + Fl_Group recorder {open + xywh {-5 49 610 457} color 53 selection_color 53 align 0 + code0 {o->set_ui(this);} + code1 {o->control->audiolib(AUDIOLIB_PORTAUDIO,(void*)(this->portaudio));} + code2 {o->control->audiolib(AUDIOLIB_JACK,(void*)(this->libjack));} + code3 {o->control->audiolib(AUDIOLIB_SNDFILE,(void*)(this->soundfile));} + class RecorderUI + } {} + } + Fl_Group tabMixer { + label Mixer open + xywh {0 45 605 463} color 52 labelfont 1 labelsize 12 hide + } { + Fl_Group mixer {open + xywh {0 49 605 456} color 53 selection_color 53 align 0 + code0 {o->set_ui(this);} + class MixerUI + } {} + } + Fl_Group tabCopyToPC { + label {Copy to PC} open + xywh {5 50 600 455} color 52 labelfont 1 labelsize 12 hide + } { + Fl_Check_Button {} { + xywh {85 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1 + code0 {track[0]=o;} + } + Fl_Check_Button {} { + xywh {105 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1 + code0 {track[1]=o;} + } + Fl_Check_Button {} { + xywh {125 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1 + code0 {track[2]=o;} + } + Fl_Check_Button {} { + xywh {145 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1 + code0 {track[3]=o;} + } + Fl_Check_Button {} { + xywh {165 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1 + code0 {track[4]=o;} + } + Fl_Check_Button {} { + xywh {185 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1 + code0 {track[5]=o;} + } + Fl_Check_Button {} { + xywh {205 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1 + code0 {track[6]=o;} + } + Fl_Check_Button {} { + xywh {225 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1 + code0 {track[7]=o;} + } + Fl_Check_Button {} { + xywh {255 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1 + code0 {track[8]=o;} + } + Fl_Check_Button {} { + xywh {275 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1 + code0 {track[9]=o;} + } + Fl_Check_Button {} { + xywh {295 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1 + code0 {track[10]=o;} + } + Fl_Check_Button {} { + xywh {315 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1 + code0 {track[11]=o;} + } + Fl_Check_Button {} { + xywh {335 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1 + code0 {track[12]=o;} + } + Fl_Check_Button {} { + xywh {355 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1 + code0 {track[13]=o;} + } + Fl_Check_Button {} { + xywh {375 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1 + code0 {track[14]=o;} + } + Fl_Check_Button {} { + xywh {395 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1 + code0 {track[15]=o;} + } + Fl_Check_Button {} { + xywh {425 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1 + code0 {track[16]=o;} + } + Fl_Check_Button {} { + xywh {445 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1 + code0 {track[17]=o;} + } + Fl_Check_Button {} { + xywh {465 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1 + code0 {track[18]=o;} + } + Fl_Check_Button {} { + xywh {485 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1 + code0 {track[19]=o;} + } + Fl_Check_Button {} { + xywh {505 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1 + code0 {track[20]=o;} + } + Fl_Check_Button {} { + xywh {525 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1 + code0 {track[21]=o;} + } + Fl_Check_Button {} { + xywh {545 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1 + code0 {track[22]=o;} + } + Fl_Check_Button {} { + xywh {565 92 20 20} down_box DOWN_BOX value 1 labelsize 12 align 1 + code0 {track[23]=o;} + } + Fl_Box {} { + label {Tracks:} + xywh {15 79 70 16} box FLAT_BOX color 52 labelsize 12 align 20 + } + Fl_Button button_invert_tracks { + label Invert + callback {int i; +for (i=0; ivalue(1-track[i]->value()); +}} + xywh {15 92 65 20} labelsize 12 align 16 + } + Fl_Box led1 { + label 01 + xywh {85 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12 + code0 {this->trackled[0]=o;} + } + Fl_Box led2 { + label 02 + xywh {105 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12 + code0 {this->trackled[1]=o;} + } + Fl_Box led3 { + label 03 + xywh {125 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12 + code0 {this->trackled[2]=o;} + } + Fl_Box led4 { + label 04 + xywh {145 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12 + code0 {this->trackled[3]=o;} + } + Fl_Box led5 { + label 05 + xywh {165 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12 + code0 {this->trackled[4]=o;} + } + Fl_Box led6 { + label 06 + xywh {185 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12 + code0 {this->trackled[5]=o;} + } + Fl_Box led7 { + label 07 + xywh {205 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12 + code0 {this->trackled[6]=o;} + } + Fl_Box led8 { + label 08 + xywh {225 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12 + code0 {this->trackled[7]=o;} + } + Fl_Box led9 { + label 09 + xywh {255 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12 + code0 {this->trackled[8]=o;} + } + Fl_Box led10 { + label 10 + xywh {275 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12 + code0 {this->trackled[9]=o;} + } + Fl_Box led11 { + label 11 + xywh {295 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12 + code0 {this->trackled[10]=o;} + } + Fl_Box led12 { + label 12 + xywh {315 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12 + code0 {this->trackled[11]=o;} + } + Fl_Box led13 { + label 13 + xywh {335 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12 + code0 {this->trackled[12]=o;} + } + Fl_Box led14 { + label 14 + xywh {355 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12 + code0 {this->trackled[13]=o;} + } + Fl_Box led15 { + label 15 + xywh {375 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12 + code0 {this->trackled[14]=o;} + } + Fl_Box led16 { + label 16 + xywh {395 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12 + code0 {this->trackled[15]=o;} + } + Fl_Box led17 { + label 17 + xywh {424 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12 + code0 {this->trackled[16]=o;} + } + Fl_Box led18 { + label 18 + xywh {444 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12 + code0 {this->trackled[17]=o;} + } + Fl_Box led19 { + label 19 + xywh {464 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12 + code0 {this->trackled[18]=o;} + } + Fl_Box led20 { + label 20 + xywh {484 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12 + code0 {this->trackled[19]=o;} + } + Fl_Box led21 { + label 21 + xywh {504 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12 + code0 {this->trackled[20]=o;} + } + Fl_Box led22 { + label 22 + xywh {524 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12 + code0 {this->trackled[21]=o;} + } + Fl_Box led23 { + label 23 + xywh {544 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12 + code0 {this->trackled[22]=o;} + } + Fl_Box led24 { + label 24 + xywh {564 80 20 14} box FLAT_BOX color 52 selection_color 0 labelsize 12 + code0 {this->trackled[23]=o;} + } + Fl_Button button_transfertopc { + label Transfer + callback {recorder->control->button_stop_call(); +mustdisplaytimer=false; +__sint64 bytestransferred=0; +transeng->sizelimit(strtoll(sizelimit->value(),0,10)); + +int bytespersam; +int wantsplit=0; +__uint32 numsongs=1; +double dif; +__sint64 totbytestotransfer=0; + +bool needoverwrite=false; +bool isproblem=false; +__uint32 channelstotransfer=0; + +__uint32 i=0; + +transfer_cancel=0; + +if (currproj==NULL) +{ +\#if (HD24DEBUG==1) + cout << "No current project." << endl; +\#endif + return; +} + +/* TODO: DISABLE/ENABLE JACK BEFORE/AFTER TRANSFER */ +//jack_client_t* saveclient=jackclient; +//jackclient=NULL; +/* TODO: DISABLE/ENABLE JACK BEFORE/AFTER TRANSFER */ + +if (!(hd24utils::dirExists(projectdir->value()))) +{ + fl_message("Project directory no longer exists.\\nPlease select another directory and try again."); + //jackclient=saveclient; +\#if (HD24DEBUG==1) + cout << "project dir no longer exists, transfer cancelled." << endl; +\#endif + + return; +} +transeng->setstatusfunction=HD24UserInterface::transferstatus; +transeng->projectdir(projectdir->value()); +transeng->set_ui((void*)this); +transeng->mixer(this->mixer->control); +transeng->soundfile=soundfile; +bool channelwarning=false; +int currfileformat=0; +bool multisong=false; +if (currsong==NULL) +{ + multisong=true; +} +else +{ + // count channels to transfer + __uint32 channels=currsong->logical_channels(); + for (unsigned int handle=0;handlevalue()!=0) + { + channelstotransfer++; + transeng->trackselected(handle,true); + } + else + { + transeng->trackselected(handle,false); + } + } + + transeng->mixleft( (transfersource_mixleft->value())==1); + transeng->mixright( (transfersource_mixright->value()) ==1); + + currfileformat=fileformat->value(); + + transeng->selectedformat(currfileformat); + + if (transeng->format_outputchannels(currfileformat)>1) + { + if ((channelstotransfer%(transeng->format_outputchannels(currfileformat)))!=0) + { + channelwarning=true; + } + } + +} + +if (multisong) +{ + numsongs=currproj->songcount(); +} +if (channelwarning) +{ + string multiple="Number of channels to export must be a multiple of "; + string* mynum=Convert::int2str(transeng->format_outputchannels(currfileformat)); + multiple+=*mynum; + if (transeng->format_outputchannels(currfileformat)==2) + { + multiple+="\\nto export to stereo pairs."; + } else { + multiple+="\\nfor export to groups of "; + multiple+=*mynum; + multiple+=" channels."; + } + fl_message("%s",multiple.c_str()); + delete mynum; +/* TODO: DISABLE/ENABLE JACK BEFORE/AFTER TRANSFER */ +// jackclient=saveclient; + + + return; + +} +if (numsongs==0) +{ +\#if (HD24DEBUG==1) + cout << "multisong transfer: no songs in current project." << endl; +\#endif + fl_message("Nothing to do!"); +/* TODO: DISABLE/ENABLE JACK BEFORE/AFTER TRANSFER */ +// jackclient=saveclient; + + return; +} +int havedoublesongname=0; +if (multisong && (numsongs>1)) +{ + // check if any song names are duplicated + hd24song* s1=NULL; + hd24song* s2=NULL; + for (unsigned i=1; igetsong(i); + string* songname1=s1->songname(); + for (unsigned int j=i+1; j<=numsongs; j++) { + if (s2!=NULL) { + delete s2; + s2=NULL; + } + s2=currproj->getsong(j); + string* songname2=s2->songname(); + if (*songname1==*songname2) { + havedoublesongname=1; + } + delete songname2; + if (havedoublesongname==1) break; + } + delete songname1; + if (havedoublesongname==1) break; + } + if (s1!=NULL) { + delete s1; + s1=NULL; + } + if (s2!=NULL) { + delete s2; + s2=NULL; + } +} +if (havedoublesongname==1) +{ + if (!confirm( + "Duplicate song names were detected. If you continue, \\n" + "exported songs will be prefixed with the song number. \\n\\n" + "If you prefer to name the songs before export, you will\\n" + "want to stop now.\\n\\n" + "Do you wish to continue?" + ) + ) { +/* TODO: DISABLE/ENABLE JACK BEFORE/AFTER TRANSFER */ +// jackclient=saveclient; + return; + }; +} +// preparation for the transfers +for (i=1; i<=numsongs; i++) +{ + if (multisong) + { + if (currsong!=NULL) { + delete currsong; + currsong=NULL; + } + currsong=currproj->getsong(i); + if (currsong!=NULL) + { + channelstotransfer=currsong->logical_channels(); + choice_startloc=0; + choice_endloc=currsong->locatepointcount(); + } + } +\#if (HD24DEBUG==1) + cout << "channels to transfer=" << channelstotransfer << endl; +\#endif + __uint64 bytestotransfer_perchannel=0; + __uint64 bytestotransfer_thissong=0; + transeng->sourcesong(currsong); + if (currsong!=NULL) + { + bytespersam=(currsong->bitdepth())/8; + // for kb/sec calculation + // because of this, double at higher sample rates + + __uint32 samstotrans_thissong; + if (multisong) + { + samstotrans_thissong=currsong->songlength_in_samples(); + transeng->startoffset(0); + transeng->endoffset(currsong->songlength_in_samples()); + } + else + { + __uint32 startoffset=0; + __uint32 endoffset=0; + + if (choice_startloc!=0) { + startoffset=currsong->getlocatepos(choice_startloc); + } + if (choice_endloc!=0) + { + endoffset=currsong->getlocatepos(choice_endloc); + } + transeng->startoffset(startoffset); + transeng->endoffset(endoffset); + if (endoffset>startoffset) + { + samstotrans_thissong=endoffset-startoffset; + } + else + { + samstotrans_thissong=startoffset-endoffset; + } + } +\#if (HD24DEBUG==1) + cout << "sams to transfer for this song=" << samstotrans_thissong << endl ; +\#endif + if (samstotrans_thissong==0xFFFFFFFF) + { + bool wanttransfer=confirm( + "You are trying to transfer the maximum song size possible\\n" + "(more than twenty hours or 300 Gigabytes of audio). \\n\\n" + "HD24tools will gladly try to perform this transfer for you,\\n" + "but it will take VERY LONG, and is probably not very helpful\\n" + "to you.\\n\\n" + "If you are currently trying to recover audio, you probably\\n" + "forgot to set the export range (with the 'Range...' button\\n" + "above). It is highly recommended to listen to your audio\\n" + "and set two locate points before setting the export range.\\n\\n" + "Do you want to perform this long and possibly useless\\n" + "transfer anyway?"); + if (!(wanttransfer)) return; + } + + bytestotransfer_perchannel=(__sint64)((__sint64)samstotrans_thissong*(__sint64)bytespersam); + + // hi-samplerate correction: + bytestotransfer_perchannel*=(currsong->physical_channels()/currsong->logical_channels()); + bytestotransfer_thissong=(channelstotransfer*bytestotransfer_perchannel); + + totbytestotransfer+=bytestotransfer_thissong; + + if (!(needoverwrite)) + { + needoverwrite=anyfilesexist(currsong); + } + } + + + /* The above number equals 2 giga/4, to bypass format limitations. + For 24-bit samples 2 giga/3 would suffice but some space could + be needed by headers etc. */ + __uint64 MAXBYTES=transeng->sizelimit(); + // max number of samples per giga is half for high samplerate files + if (multisong) + { + delete currsong; + currsong=NULL; + } +\#if (HD24DEBUG==1) + cout << "Maxbytes per channel=" << MAXBYTES ; + cout << "bytes per channel=" << bytestotransfer_perchannel << endl; +\#endif + if (bytestotransfer_perchannel>MAXBYTES) + { + if (wantsplit!=1) + { +/* + int choice=fl_choice( + "Exported audio files may be too large to play or edit. \\nDo you want to export the file as multiple smaller chunks?", + "Yes","No","Cancel" + ); + if (choice==2) + { +\#if (HD24DEBUG==1) + cout << "user cancelled too large file transfer" << endl; +\#endif + //jackclient=saveclient; + return; // cancelled + } + if (choice==0) + { + wantsplit=1; + } +*/ + if (autosplit->value()==1) { + wantsplit=1; + } + } + } +} +if (multisong) +{ + if (currsong!=NULL) { + delete currsong; + currsong=NULL; + } +} + +// do we need to overwrite any files? Are we allowed to? +if (needoverwrite) +{ + isproblem=(!(confirm("One or more output files already exist. Do you want to overwrite them?"))); +} + +if (isproblem) +{ +\#if (HD24DEBUG==1) + cout << "user does not wish to perform needed overwrite." << endl; +\#endif +/* TODO: DISABLE/ENABLE JACK BEFORE/AFTER TRANSFER */ +// jackclient=saveclient; + return; +} + +// needed to check for dir to make sure about existence of output files +// but the previous question may have given the user the time to mess up. +// check the dir again :) + +if (!(hd24utils::dirExists(projectdir->value()))) +{ + fl_message("Project directory no longer exists.\\nPlease select another directory and try again."); +/* TODO: DISABLE/ENABLE JACK BEFORE/AFTER TRANSFER */ +// jackclient=saveclient; +\#if (HD24DEBUG==1) + cout << "project directory deleted" << endl; +\#endif + return; +} +\#if (HD24DEBUG==1) + cout << "by calc, tot bytes to transfer=" << totbytestotransfer << endl; +\#endif + +deactivate_ui(); +setstatus("Transferring audio to PC... 0%"); +time (&starttime); +int somethingwrong=0; +for (i=1; i<=numsongs; i++) +{ +\#if (HD24DEBUG==1) + cout << "set song" << endl; +\#endif + if (transfer_cancel!=0) + { +\#if (HD24DEBUG==1) + cout << "transfer cancelled by user." << endl; +\#endif + break; + } + + if (multisong) + { + if (currsong!=NULL) { + delete currsong; + currsong=NULL; + } + currsong=currproj->getsong(i); + } + transeng->sourcesong(currsong); + if (currsong==NULL) + { +\#if (HD24DEBUG==1) + cout << "currsong=null, nothing to transfer" << endl; +\#endif + continue; + } +\#if (HD24DEBUG==1) + cout << "calling ftransfer with "; + cout << "sonnum=" << i; + cout << ", numsongs=" << numsongs; + cout << ", totlen(bytes)=" << totbytestotransfer; + cout << ", bytestransferred=" << bytestransferred; + cout << ", wantsplit=" << wantsplit << endl; +\#endif + + transeng->prepare_transfer_to_pc(i,numsongs,totbytestotransfer,bytestransferred,wantsplit,(havedoublesongname==1)?(i):(0)); + __sint64 currtransferred=transeng->transfer_to_pc(); + if (currtransferred==0) + { + somethingwrong=1; + break; + } + bytestransferred+=currtransferred; + + if (multisong) + { + delete currsong; + currsong=NULL; + } + +} + + +if (multisong) +{ + if (currsong!=NULL) + { + delete currsong; + currsong=NULL; + } +} + +/* TODO: DISABLE/ENABLE JACK BEFORE/AFTER TRANSFER */ +//jackclient=saveclient; +if (somethingwrong==1) +{ + activate_ui(); + if (transeng->lasterror()!=NULL) + { + + setstatus(transeng->lasterror()->c_str()); + } + else + { + setstatus((const char*)&"Unexpected error transferring files."); + } + stop_transfer->hide(); + return; +} + +time (&endtime); +dif=difftime(endtime,starttime); +//__uint32 subsecs=(__uint32)(100*(dif-floor(dif))); +dif=floor(dif); +__uint32 minutes=((__uint32)dif-((__uint32)dif%60))/60; +__uint32 seconds=((__uint32)dif%60); + +string minsec="Ready. Transfer time: "; +if (transfer_cancel==1) +{ + minsec="Transfer cancelled. Elapsed transfer time: "; +} +transfer_cancel=0; +string* strmins=Convert::int2str(minutes,2,"0"); +minsec+=*strmins; +delete (strmins); +minsec+=":"; +string* strsecs=Convert::int2str(seconds,2,"0"); +minsec+=*strsecs; +delete(strsecs); + +if (dif>=1) +{ + __uint32 kbps=(__uint32)(((bytestransferred)/1024)/dif); + + minsec+=" ("; + string* strkbps=Convert::int2str(kbps); + minsec+=*strkbps; + minsec+=" kB/sec)"; + delete(strkbps); +} +activate_ui(); +setstatus(minsec.c_str()); +stop_transfer->hide();} + xywh {530 480 70 20} labelsize 12 align 16 + code0 {o->label("Transfer");} + } + Fl_Button {} { + label {Browse...} + callback {Fl_Native_File_Chooser chooser; +chooser.title("Select project directory"); +chooser.type(Fl_Native_File_Chooser::BROWSE_DIRECTORY); +chooser.options(Fl_Native_File_Chooser::NEW_FOLDER); +chooser.filter(""); + +string currdir=""; +currdir+=projectdir->value(); + +chooser.directory(currdir.c_str()); +switch (chooser.show()) { + case -1: break; //error + case 1: break; //cancel + default: + if (chooser.filename()) { + projectdir->value(chooser.filename()); + hd24utils::setlastdir("projdir",chooser.filename()); + } + + break; +}} + xywh {505 175 85 20} labelsize 12 align 16 + } + Fl_Input projectdir { + label {Project dir:} + callback {/* callback when release: add a + (back)slash to the end of the + pathname if one is not present. */ + +\#ifdef WINDOWS +\#define MYSLASH '\\\\' +\#else +\#define MYSLASH '/' +\#endif +char* x=(char*)projectdir->value(); +if (strlen(x)==0) { + x[0]=MYSLASH; + x[1]=0; +} else { + int q=strlen(x); + if (x[q-1]!=MYSLASH) { + x[q]=MYSLASH; + x[q+1]=0; + } +} +projectdir->value(x); +hd24utils::setlastdir("projdir",projectdir->value());} + xywh {85 175 415 20} labelsize 12 textsize 12 + code0 {getlastprojdir(o);} + code1 {/*o->clear_visible_focus();*/} + } + Fl_Output fromtime { + label {From:} + xywh {265 115 105 20} labelsize 12 textsize 12 + code0 {o->clear_visible_focus();} + } + Fl_Output totime { + label {To:} + xywh {395 115 105 20} labelsize 12 textsize 12 + code0 {o->clear_visible_focus();} + } + Fl_Button fromto { + label {Range...} + callback {if (currsong==NULL) return; +dialog_fromto* ui_fromto; +ui_fromto=new dialog_fromto; + +Fl_Window *win=ui_fromto->make_window(currsong); +populate_locatepoints(currsong,ui_fromto->fromloc); +populate_locatepoints(currsong,ui_fromto->toloc); +ui_fromto->fromloc->value(choice_startloc); +ui_fromto->toloc->value(choice_endloc); +win->end(); +win->show(); + +while (win->visible()) { Fl::wait(); } + +/* Dialog has closed, read the results */ +//if (ui_fromto->buttonclicked==0) +//{ fl_message("No OK nor Cancel clicked"); } +if (ui_fromto->buttonclicked==1) +{ + // OK clicked + choice_startloc=ui_fromto->choice_startloc; + choice_endloc=ui_fromto->choice_endloc; + update_fromto(); +} +//if (ui_fromto->buttonclicked==2) +//{ fl_message("Cancel clicked"); } +delete ui_fromto;} + xywh {505 115 85 20} labelsize 12 align 16 + } + Fl_Choice fileformat { + label {File format:} open + xywh {85 200 160 20} down_box BORDER_BOX labelsize 12 textsize 12 + } {} + Fl_Check_Button autosplit { + label {Automatically limit size of exported files} + callback {if (autosplit->value()==1) { + sizelimitdropdown->activate(); + + if (sizelimitdropdown->value()==6) { + sizelimit->activate(); + } else { + sizelimit->deactivate(); + } +} else { + sizelimitdropdown->deactivate(); + sizelimit->deactivate(); +}} + xywh {10 265 20 20} box FLAT_BOX down_box DOWN_BOX value 1 color 52 labelsize 12 align 8 + } + Fl_Input sizelimit { + label bytes + xywh {425 290 120 20} labelsize 12 align 8 textsize 12 + code0 {long long x=1073741824LL; string* sval=Convert::int64tostr(x); o->value(sval->c_str()); delete sval; o->deactivate();} + code1 {o->maximum_size(17);} + } + Fl_Box {} { + label {Transfer target:} + xywh {10 153 305 17} box FLAT_BOX color 52 labelfont 1 labelsize 12 align 20 + } + Fl_Box {} { + label {Transfer options:} + xywh {10 243 305 17} box FLAT_BOX color 52 labelfont 1 labelsize 12 align 20 + } + Fl_Box {} { + label {Note: The actual file size will be a rough approximation of the requested split size.} + xywh {30 318 550 17} box FLAT_BOX color 52 labelfont 2 labelsize 12 align 20 + } + Fl_Check_Button customrate { + label {Stamp files with a custom sample rate} + callback {if (customrate->value()==1) { + ratechoice->activate(); + if (ratechoice->value()==4) { + stamprate->activate(); + } else { + stamprate->deactivate(); + } +} else { + ratechoice->deactivate(); + stamprate->deactivate(); +}} + xywh {10 345 20 20} box FLAT_BOX down_box DOWN_BOX color 52 labelsize 12 align 8 + } + Fl_Choice ratechoice { + label {Sample rate:} open + xywh {105 370 295 20} down_box BORDER_BOX labelsize 12 textsize 12 deactivate + code0 {o->value(1);} + } { + MenuItem {} { + label {44100 Hz} + callback {long long x=44100LL; +string* sval=Convert::int64tostr(x); +stamprate->value(sval->c_str()); +delete sval; +stamprate->deactivate();} + xywh {25 25 36 21} labelsize 12 + } + MenuItem {} { + label {48000 Hz} + callback {long long x=48000LL; +string* sval=Convert::int64tostr(x); +stamprate->value(sval->c_str()); +delete sval; +stamprate->deactivate();} + xywh {35 35 36 21} labelsize 12 + } + MenuItem {} { + label {88200 Hz} + callback {long long x=88200LL; +string* sval=Convert::int64tostr(x); +stamprate->value(sval->c_str()); +delete sval; +stamprate->deactivate();} + xywh {45 45 36 21} labelsize 12 + } + MenuItem {} { + label {96000 Hz} + callback {long long x=96000LL; +string* sval=Convert::int64tostr(x); +stamprate->value(sval->c_str()); +delete sval; +stamprate->deactivate();} + xywh {55 55 36 21} labelsize 12 + } + MenuItem {} { + label {User defined, specify -->} + callback {stamprate->activate();} + xywh {85 85 36 21} labelsize 12 + } + } + Fl_Input stamprate { + label Hz + xywh {425 370 120 20} labelsize 12 align 8 textsize 12 deactivate + code0 {long long x=48000; string* sval=Convert::int64tostr(x); o->value(sval->c_str()); delete sval; o->deactivate();} + code1 {o->maximum_size(5);} + } + Fl_Choice sizelimitdropdown { + label {Split every:} open + tooltip 1 xywh {105 290 295 20} down_box BORDER_BOX labelsize 12 textsize 12 + code0 {o->value(2);} + } { + MenuItem {} { + label {650 MB (74 minute CD)} + callback {long long x=650000000LL; +string* sval=Convert::int64tostr(x); +sizelimit->value(sval->c_str()); +delete sval; +sizelimit->deactivate();} + xywh {20 20 36 21} labelsize 12 + } + MenuItem {} { + label {700 MB (80 minute CD)} + callback {long long x=700000000LL; +string* sval=Convert::int64tostr(x); +sizelimit->value(sval->c_str()); +delete sval; +sizelimit->deactivate();} + xywh {30 30 36 21} labelsize 12 + } + MenuItem {} { + label {1 GiB (Recommended for wave editors)} + callback {long long x=1073741824LL; +string* sval=Convert::int64tostr(x); +sizelimit->value(sval->c_str()); +delete sval; +sizelimit->deactivate();} + xywh {40 40 36 21} labelsize 12 + } + MenuItem {} { + label {2 GiB (Max. legal WAV size)} + callback {long long x=2147483648LL; +string* sval=Convert::int64tostr(x); +sizelimit->value(sval->c_str()); +delete sval; +sizelimit->deactivate();} + xywh {50 50 36 21} labelsize 12 + } + MenuItem {} { + label {4 GiB (Max. 32-bit limit)} + callback {long long x=4294967296LL; +string* sval=Convert::int64tostr(x); +sizelimit->value(sval->c_str()); +delete sval; +sizelimit->deactivate();} + xywh {60 60 36 21} labelsize 12 + } + MenuItem {} { + label {4.7 GB (DVD size)} + callback {long long x=4700000000LL; +string* sval=Convert::int64tostr(x); +sizelimit->value(sval->c_str()); +delete sval; +sizelimit->deactivate();} + xywh {70 70 36 21} labelsize 12 + } + MenuItem {} { + label {User defined, specify -->} + callback {sizelimit->activate();} + xywh {80 80 36 21} labelsize 12 + } + } + Fl_Check_Button transfersource_mixleft { + label {Mixer Left} + callback {saverestoretrackselection(o);} + xywh {85 115 20 20} down_box DOWN_BOX labelsize 12 align 4 + } + Fl_Check_Button transfersource_mixright { + label Right + callback {saverestoretrackselection(o);} + xywh {105 115 20 20} down_box DOWN_BOX labelsize 12 align 8 + } + Fl_Group batch_stuff { + label {batch stuff } open + xywh {5 390 600 115} align 16 hide deactivate + } { + Fl_Box {} { + label {Batch transfer list:} + xywh {10 393 305 17} box FLAT_BOX color 52 labelfont 1 labelsize 12 align 20 deactivate + } + Fl_Output transfer_list { + xywh {10 410 515 90} type Multiline labelsize 12 textsize 12 deactivate + code0 {o->clear_visible_focus();} + } + Fl_Button button_addtobatch { + label {To Batch} + xywh {530 410 70 20} labelsize 12 align 16 deactivate + } + Fl_Button button_removefrombatch { + label Remove + xywh {530 430 70 20} labelsize 12 align 16 deactivate + } + } + Fl_Output transfersource { + label {Transfer source:} + xywh {127 57 458 20} box NO_BOX labelfont 1 labelsize 12 textsize 12 + } + Fl_Button {} { + label {?} + callback {fl_message("This option allows you to limit the size of exported files. \\n" +"In the dropdown box, the following units are used:\\n\\n" +"MB - Megabyte, 1000x1000 bytes\\n" +"GB - Gigabyte, 1000x1000x1000 bytes\\n" +"GiB - Binary Gigabyte or Gibibyte, 1024x1024x1024 bytes\\n\\n" +"In any situation, the actual byte count is displayed on the right.");} + 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 + } + Fl_Button {} { + label {?} + callback {fl_message("Stamping files with another sample rates allows you \\n" +"to export files with a sample rate that differs from the sample \\n" +"rate at which the song was recorded. When using this option, \\n" +"note that no resampling takes place; both the pitch and playback \\n" +"speed will change compared to the original sample rate. ");} + 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 + } + } + Fl_Group tab_tohd24 { + label {Copy to HD24} open + xywh {0 45 605 461} color 52 labelfont 1 labelsize 12 + } { + Fl_Button button_transfertohd24 { + label Transfer + callback {recorder->control->button_stop_call(); //stop transport +bool have_smpte=false; +if (currproj==NULL) +{ + fl_message("No project selected, nothing to do!\\nSelect a project on the Project/Song tab and try again."); + return; +} +if (currsong==NULL) +{ + fl_message("No song selected, nothing to do!\\nSelect a song on the Project/Song tab and try again."); + return; +} + +int havefiles=0; +for (unsigned int ch=1;ch<=currsong->logical_channels();ch++) { + + if (strlen(filename[ch-1]->value())>0) { + // track has a file selected + havefiles=1; + currsong->trackarmed(ch,true); + continue; + } + int action=((Fl_Choice*)(trackaction[ch-1]))->value(); + if (action==0) { /* 0=ERASE */ + // track action says 'erase' + havefiles=1; + currsong->trackarmed(ch,true); + continue; + } + if (action==1) { /* 1=SMPTE */ + // track action says 'stripe with SMPTE/LTC' + havefiles=1; + have_smpte=true; + currsong->trackarmed(ch,true); + continue; + } + // no file, no timecode stripe and no erase, keep track. + currsong->trackarmed(ch,false); + +} +if (havefiles==0) { + fl_message( + "To transfer files to the HD24, load one or more files.\\n" + "Each file will be assigned to an empty track slot.\\n\\n" + "Before transferring, you will be able to rearrange the\\n" + "order of the tracks by clicking on one or more tracks\\n" + "and clicking the up or down arrow buttons.\\n\\n" + "When a track slot is empty, the existing track will be\\n" + "preserved, unless 'Erase' or 'SMPTE' is selected on \\n" + "the right of the track.\\n\\n" + "When a file to transfer contains multiple tracks, you\\n" + "can choose to mixdown the file to mono (the default), \\n" + "or you can select the track that you want to transfer \\n" + "to the HD24 drive." + ); + for (unsigned int ch=1;ch<=currsong->logical_channels();ch++) { + currsong->trackarmed(ch,false); + } + return; +} +if (currsong->iswriteprotected()) +{ + fl_message("The song is write protected."); + for (unsigned int ch=1;ch<=currsong->logical_channels();ch++) { + currsong->trackarmed(ch,false); + } + return; +} +// ask ARE YOU SURE???? +bool sure=confirm("Are you sure you want to overwrite the existing audio?"); +if (!sure) return; + +// check if all files still exist + +int filemissing=0; +for (unsigned int misscheck=1;misscheck<=currsong->logical_channels();misscheck++) { + if (strlen(filename[misscheck-1]->value())==0) continue; + if (!(hd24utils::fileExists(filename[misscheck-1]->value()))) + { + filemissing=1; + break; + } +} + +if (filemissing==1) { + fl_message("One or more files no longer exist. \\nPlease clear and reload the files, then try again."); + return; +} +// end of checking if all files still exist +transeng->targetsong(currsong); +transeng->soundfile=soundfile; +for (unsigned int filenum=1;filenum<=currsong->logical_channels();filenum++) +{ + transeng->sourcefilename(filenum,filename[filenum-1]->value()); + transeng->trackaction(filenum,((Fl_Choice*)(trackaction[filenum-1]))->value()); +} +transeng->transfer_to_hd24(); +stop_transfer->hide(); +if (transeng->lasterror()!=NULL) +{ + if (transeng->lasterror()->c_str()!=NULL) + { + setstatus(transeng->lasterror()->c_str()); + } + else + { + setstatus("Done. No error messages."); + } +} else { + setstatus("Done."); +} +ui_refresh("tohd24_done"); +activate_ui(); +fl_check();} selected + xywh {530 480 70 20} labelsize 12 + } + Fl_Output filename1 { + label {01 } + callback {selectfilename(1);} + xywh {40 50 430 19} labelfont 1 labelsize 12 textsize 12 + code0 {filename[0]=o;} + } + Fl_Output filename2 { + label {02 } + callback {selectfilename(2);} + xywh {40 69 430 19} labelfont 1 labelsize 12 textsize 12 + code0 {filename[1]=o;} + } + Fl_Output filename3 { + label {03 } + callback {selectfilename(3);} + xywh {40 88 430 19} labelfont 1 labelsize 12 textsize 12 + code0 {filename[2]=o;} + } + Fl_Output filename4 { + label {04 } + callback {selectfilename(4);} + xywh {40 107 430 19} labelfont 1 labelsize 12 textsize 12 + code0 {filename[3]=o;} + } + Fl_Output filename5 { + label {05 } + callback {selectfilename(5);} + xywh {40 126 430 19} labelfont 1 labelsize 12 textsize 12 + code0 {filename[4]=o;} + } + Fl_Output filename6 { + label {06 } + callback {selectfilename(6);} + xywh {40 145 430 19} labelfont 1 labelsize 12 textsize 12 + code0 {filename[5]=o;} + } + Fl_Output filename7 { + label {07 } + callback {selectfilename(7);} + xywh {40 164 430 19} labelfont 1 labelsize 12 textsize 12 + code0 {filename[6]=o;} + } + Fl_Output filename8 { + label {08 } + callback {selectfilename(8);} + xywh {40 183 430 19} labelfont 1 labelsize 12 textsize 12 + code0 {filename[7]=o;} + } + Fl_Output filename9 { + label {09 } + callback {selectfilename(9);} + xywh {40 202 430 19} labelfont 1 labelsize 12 textsize 12 + code0 {filename[8]=o;} + } + Fl_Output filename10 { + label {10 } + callback {selectfilename(10);} + xywh {40 221 430 19} labelfont 1 labelsize 12 textsize 12 + code0 {filename[9]=o;} + } + Fl_Output filename11 { + label {11 } + callback {selectfilename(11);} + xywh {40 240 430 19} labelfont 1 labelsize 12 textsize 12 + code0 {filename[10]=o;} + } + Fl_Output filename12 { + label {12 } + callback {selectfilename(12);} + xywh {40 259 430 19} labelfont 1 labelsize 12 textsize 12 + code0 {filename[11]=o;} + } + Fl_Output filename13 { + label {13 } + callback {selectfilename(13);} + xywh {40 278 430 19} labelfont 1 labelsize 12 textsize 12 + code0 {filename[12]=o;} + } + Fl_Output filename14 { + label {14 } + callback {selectfilename(14);} + xywh {40 297 430 19} labelfont 1 labelsize 12 textsize 12 + code0 {filename[13]=o;} + } + Fl_Output filename15 { + label {15 } + callback {selectfilename(15);} + xywh {40 316 430 19} labelfont 1 labelsize 12 textsize 12 + code0 {filename[14]=o;} + } + Fl_Output filename16 { + label {16 } + callback {selectfilename(16);} + xywh {40 335 430 19} labelfont 1 labelsize 12 textsize 12 + code0 {filename[15]=o;} + } + Fl_Output filename17 { + label {17 } + callback {selectfilename(17);} + xywh {40 354 430 19} labelfont 1 labelsize 12 textsize 12 + code0 {filename[16]=o;} + } + Fl_Output filename18 { + label {18 } + callback {selectfilename(18);} + xywh {40 373 430 19} labelfont 1 labelsize 12 textsize 12 + code0 {filename[17]=o;} + } + Fl_Output filename19 { + label {19 } + callback {selectfilename(19);} + xywh {40 392 430 19} labelfont 1 labelsize 12 textsize 12 + code0 {filename[18]=o;} + } + Fl_Output filename20 { + label {20 } + callback {selectfilename(20);} + xywh {40 411 430 19} labelfont 1 labelsize 12 textsize 12 + code0 {filename[19]=o;} + } + Fl_Output filename21 { + label {21 } + callback {selectfilename(21);} + xywh {40 430 430 19} labelfont 1 labelsize 12 textsize 12 + code0 {filename[20]=o;} + } + Fl_Output filename22 { + label {22 } + callback {selectfilename(22);} + xywh {40 449 430 19} labelfont 1 labelsize 12 textsize 12 + code0 {filename[21]=o;} + } + Fl_Output filename23 { + label {23 } + callback {selectfilename(23);} + xywh {40 468 430 19} labelfont 1 labelsize 12 textsize 12 + code0 {filename[22]=o;} + } + Fl_Output filename24 { + label {24 } + callback {selectfilename(24);} + xywh {40 487 430 19} labelfont 1 labelsize 12 textsize 12 + code0 {filename[23]=o;} + } + Fl_Repeat_Button button_moveup { + callback {moveselected(-1);} + image {images/up.gif} xywh {530 255 70 20} labelsize 12 align 17 + } + Fl_Repeat_Button button_movedown { + callback {moveselected(1);} + image {images/down.gif} xywh {530 275 70 20} labelsize 12 + } + Fl_Button button_load { + label {Load...} + callback {if (currsong == NULL) { + fl_message("No song selected.\\nSelect a song on the Project/Song tab and try again."); + return; + return; +} +string* audiofiledir=hd24utils::getlastdir("audiofiledir"); + +Fl_Native_File_Chooser chooser; +chooser.directory(audiofiledir->c_str()); +delete audiofiledir; +chooser.title("Select the files to transfer:\\0"); +chooser.type(Fl_Native_File_Chooser::BROWSE_MULTI_FILE); +chooser.filter("Audio files\\t*.{wav,aif}\\0"); +//chooser.preview(0); +int tosplitornottosplit=0; + +switch (chooser.show()) { + case -1: break; //error + case 1: break; //cancel + default: + if (chooser.filename()) { + string* cfilename=new string(chooser.filename()); + + string* fpath=new string(""); + *fpath+=cfilename->substr(0,strlen(cfilename->c_str())-strlen(fl_filename_name(cfilename->c_str()))); + hd24utils::setlastdir("audiofiledir",fpath->c_str()); + delete cfilename; + for (int n = 0; n < chooser.count(); n++ ) { + string* cfilename=new string(chooser.filename(n)); + int currfiletracks=countfiletracks(cfilename->c_str()); + int totfiletracks=currfiletracks; + int haveslot=0; + while (currfiletracks>0) { + if (totfiletracks>1) { + if (tosplitornottosplit==0) { + bool wantsplit= + confirm("One or more selected files have more than 1 track. Do you wish to split them up?"); + if (!wantsplit) { + tosplitornottosplit=1; + } else { + tosplitornottosplit=2; + } + } + } + + haveslot=0; + for (unsigned int freeslot=0;freeslotlogical_channels();freeslot++) { + if (strlen(filename[freeslot]->value())==0) { + haveslot=1; + filename[freeslot]->value(chooser.filename(n)); +// cout << "Clear slot " << freeslot << endl; + ((Fl_Choice*)(trackaction[freeslot]))->clear(); + if (tosplitornottosplit>1) { + populate_trackactionbyfile(freeslot,3+(totfiletracks-currfiletracks)); + } else { + populate_trackactionbyfile(freeslot,2); + } + break; + } + } + if (haveslot==0) { + break; + } + if (tosplitornottosplit==1) { + currfiletracks=0; + } else { + currfiletracks--; + } + } + delete cfilename; + if (haveslot==0) { + fl_message("One or more files could not be assigned to a track slot.\\n" + "Please clear one or more track slots and try again."); + break; + } + } + } +}} + xywh {530 50 70 20} labelsize 12 + } + Fl_Button button_clear { + label Clear + callback {for (unsigned int i=0;ivalue(""); + trackselected[i]=0; + + } +}; +redrawtracks();} + xywh {530 70 70 20} labelsize 12 + } + Fl_Choice trackaction1 {open + xywh {470 50 55 19} down_box BORDER_BOX labelsize 11 textsize 11 + code0 {this->populate_trackaction(this,o,1);} + } {} + Fl_Choice trackaction2 {open + xywh {470 69 55 19} down_box BORDER_BOX labelsize 11 textsize 11 + code0 {this->populate_trackaction(this,o,2);} + } {} + Fl_Choice trackaction3 {open + xywh {470 88 55 19} down_box BORDER_BOX labelsize 11 textsize 11 + code0 {this->populate_trackaction(this,o,3);} + } {} + Fl_Choice trackaction4 {open + xywh {470 107 55 19} down_box BORDER_BOX labelsize 11 textsize 11 + code0 {this->populate_trackaction(this,o,4);} + } {} + Fl_Choice trackaction5 {open + xywh {470 126 55 19} down_box BORDER_BOX labelsize 11 textsize 11 + code0 {this->populate_trackaction(this,o,5);} + } {} + Fl_Choice trackaction6 {open + xywh {470 145 55 19} down_box BORDER_BOX labelsize 11 textsize 11 + code0 {this->populate_trackaction(this,o,6);} + } {} + Fl_Choice trackaction7 {open + xywh {470 164 55 19} down_box BORDER_BOX labelsize 11 textsize 11 + code0 {this->populate_trackaction(this,o,7);} + } {} + Fl_Choice trackaction8 {open + xywh {470 183 55 19} down_box BORDER_BOX labelsize 11 textsize 11 + code0 {this->populate_trackaction(this,o,8);} + } {} + Fl_Choice trackaction9 {open + xywh {470 202 55 19} down_box BORDER_BOX labelsize 11 textsize 11 + code0 {this->populate_trackaction(this,o,9);} + } {} + Fl_Choice trackaction10 {open + xywh {470 221 55 19} down_box BORDER_BOX labelsize 11 textsize 11 + code0 {this->populate_trackaction(this,o,10);} + } {} + Fl_Choice trackaction11 {open + xywh {470 240 55 19} down_box BORDER_BOX labelsize 11 textsize 11 + code0 {this->populate_trackaction(this,o,11);} + } {} + Fl_Choice trackaction12 {open + xywh {470 259 55 19} down_box BORDER_BOX labelsize 11 textsize 11 + code0 {this->populate_trackaction(this,o,12);} + } {} + Fl_Choice trackaction13 {open + xywh {470 278 55 19} down_box BORDER_BOX labelsize 11 textsize 11 + code0 {this->populate_trackaction(this,o,13);} + } {} + Fl_Choice trackaction14 {open + xywh {470 297 55 19} down_box BORDER_BOX labelsize 11 textsize 11 + code0 {this->populate_trackaction(this,o,14);} + } {} + Fl_Choice trackaction15 {open + xywh {470 316 55 19} down_box BORDER_BOX labelsize 11 textsize 11 + code0 {this->populate_trackaction(this,o,15);} + } {} + Fl_Choice trackaction16 {open + xywh {470 335 55 19} down_box BORDER_BOX labelsize 11 textsize 11 + code0 {this->populate_trackaction(this,o,16);} + } {} + Fl_Choice trackaction17 {open + xywh {470 354 55 19} down_box BORDER_BOX labelsize 11 textsize 11 + code0 {this->populate_trackaction(this,o,17);} + } {} + Fl_Choice trackaction18 {open + xywh {470 373 55 19} down_box BORDER_BOX labelsize 11 textsize 11 + code0 {this->populate_trackaction(this,o,18);} + } {} + Fl_Choice trackaction19 {open + xywh {470 392 55 19} down_box BORDER_BOX labelsize 11 textsize 11 + code0 {this->populate_trackaction(this,o,19);} + } {} + Fl_Choice trackaction20 {open + xywh {470 411 55 19} down_box BORDER_BOX labelsize 11 textsize 11 + code0 {this->populate_trackaction(this,o,20);} + } {} + Fl_Choice trackaction21 {open + xywh {470 430 55 19} down_box BORDER_BOX labelsize 11 textsize 11 + code0 {this->populate_trackaction(this,o,21);} + } {} + Fl_Choice trackaction22 {open + xywh {470 449 55 19} down_box BORDER_BOX labelsize 11 textsize 11 + code0 {this->populate_trackaction(this,o,22);} + } {} + Fl_Choice trackaction23 {open + xywh {470 468 55 19} down_box BORDER_BOX labelsize 11 textsize 11 + code0 {this->populate_trackaction(this,o,23);} + } {} + Fl_Choice trackaction24 {open + xywh {470 487 55 19} down_box BORDER_BOX labelsize 11 textsize 11 + code0 {this->populate_trackaction(this,o,24);} + } {} + Fl_Button button_transfertohd24help { + label Help + callback {fl_message( + "To transfer files to the HD24, load one or more files.\\n" + "Each file will be assigned to an empty track slot.\\n\\n" + "Before transferring, you will be able to rearrange the\\n" + "order of the tracks by clicking on one or more tracks\\n" + "and clicking the up or down arrow buttons.\\n\\n" + "When a track slot is empty, the existing track will be\\n" + "preserved, unless 'Erase' or 'SMPTE' is selected on \\n" + "the right of the track.\\n\\n" + "When a file to transfer contains multiple tracks, you\\n" + "can choose to mixdown the file to mono (the default), \\n" + "or you can select the track that you want to transfer \\n" + "to the HD24 drive." + );} + xywh {530 455 70 20} labelsize 12 + } + } + } + Fl_Group uicanvas_futureversions {open + xywh {5 10 1710 530} hide resizable + } { + Fl_Tabs Future_Tabs {open + xywh {10 35 1595 485} + } { + Fl_Group tab_wave { + label Wave open + xywh {15 60 595 455} color 52 labelfont 1 labelsize 12 deactivate + code0 {o->hide();} + } { + Fl_Box {} { + label {A future version of HD24connect may display a wave form here. +Initially, the purpose of this wave form would be to make it +easier to select an export range.} + xywh {15 68 460 222} align 21 + } + } + Fl_Group tab_data { + label Data open + xywh {15 60 595 455} color 52 labelfont 1 labelsize 12 hide deactivate + code0 {o->hide();} + } { + Fl_Box {} { + label {A future version of HD24connect may display a list of data files here. +Specifically, this would be a list of files associated with the current +project and/or song. To make this possible, a single song on the +HD24 drive may be sacrificed as data area. This tab would then contain +functionality to import/export/list those files, as well as functionality to +create a data area on the drive. +Without data area on the HD24 drive itself, songs may still be given a +unique identifier to allow, for instance, automatically associating a mix +on the DAW computer with a song. } + xywh {15 63 505 222} align 21 + } + } + } + } + } + } + } + } + Function {make_cli(hd24fs* p_fsys)} {return_type void + } { + code {// make_cli: stands for make commandline interface +// (intended to allow batch processing and regression testing) +// both current and default to allow multi drive support +defaulthd24=p_fsys; +currenthd24=p_fsys;} {} + } + decl {/* ===RECORDER UI stuff ===================================================== */} {} + Function {readmixer()} {open return_type void + } { + code {// set solo status of channel to value +/* +for (unsigned int i=0;ivalue(mixer->mixerchannel[i]->control->solo()); + solobutton[i]->redraw(); + mutebutton[i]->value(mixer->mixerchannel[i]->control->mute()); + mutebutton[i]->redraw(); +} +*/} {} + } + decl {/* === UTILS ===================================================== */} {} + Function {getlastprojdir(Fl_Input* o)} {return_type void + } { + code {string* projdir=hd24utils::getlastdir("projdir"); +o->value(projdir->c_str()); +delete projdir;} {} + } + Function {ui_restart()} {open + } { + code {//if (isportaudioinitialized()) { +// portaudio_transport_stop(); +//} +if (recorder!=NULL) { + if (recorder->control!=NULL) { + recorder->control->button_stop_call(); + } +} +Fl::remove_timeout(poll_callback); + +recorder->~RecorderUI(); +delete recorder; + +Fl_Window * winx=Fl::first_window(); +if (currproj!=NULL) +{ + delete currproj; + currproj=NULL; +} + +if (currsong!=NULL) +{ + delete currsong; + currsong=NULL; +} + +Fl_Window * winy=make_window(currenthd24); + +winy->position(winx->x(),winx->y()); +winy->end(); +winy->show(); +\#ifdef LINUX +XSetWMHints(fl_display, fl_xid(winy), XGetWMHints(fl_display, fl_xid(winx))); +\#endif +winx->~Fl_Window(); +delete winx; +winx=NULL; +//if (jackmtsample!=NULL) +//{ +// free(jackmtsample); +//}} {} + } + Function {loadheaderfile()} {} { + code {Fl_Native_File_Chooser chooser; +chooser.title("Select header file\\0"); +chooser.filter("Drive Images\\t*.{img,bin,h24,hd24}\\0"); +chooser.type(Fl_Native_File_Chooser::BROWSE_FILE); + +string* headerdir=hd24utils::getlastdir("headerdir"); +chooser.directory(headerdir->c_str()); +delete headerdir; +switch (chooser.show()) { + case -1: break; //error + case 1: break; //cancel + default: + if (chooser.filename()) { + if (!(currenthd24->useheaderfile (chooser.filename()))) { + 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."); + return; + } + string* strfile=new string(chooser.filename()); + string* fpath=new string(""); + *fpath+=strfile->substr(0,strlen(strfile->c_str())-strlen(fl_filename_name(strfile->c_str()))); + hd24utils::setlastdir("headerdir",fpath->c_str()); + ui_restart(); + return; + } + break; +}} {} + } + Function {anyfilesexist(hd24song* thesong)} {return_type bool + } { + code {bool anyexist=false; + +struct stat fi; +__uint32 channels=thesong->logical_channels(); +for (unsigned int q=0; q<100; q++) +{ + for (unsigned int handle=0;handlevalue()==0) { + // channel not selected for export + continue; + } + string* fname=transeng->generate_filename(handle,0,q); +\#if (HD24DEBUG==1) + cout << "check if file exists:" << *fname << endl; +\#endif + if ((stat (fname->c_str(), &fi) != -1) && ((fi.st_mode & S_IFDIR) == 0)) { + anyexist=true; +\#if (HD24DEBUG==1) + cout << "yes, exists" << *fname << endl; +\#endif + delete fname; + break; + } + + fname=transeng->generate_filename(handle,1,q); +\#if (HD24DEBUG==1) + cout << "check if file exists:" << *fname << endl; +\#endif + if ((stat (fname->c_str(), &fi) != -1) && ((fi.st_mode & S_IFDIR) == 0)) { + anyexist=true; +\#if (HD24DEBUG==1) + cout << "yes, exists" << *fname << endl; +\#endif + delete fname; + break; + } +\#if (HD24DEBUG==1) + cout << "no, doesnt exist" << endl; +\#endif + + delete fname; + } + if (anyexist==true) break; +} +return anyexist;} {} + } + Function {fl_check()} {open return_type void + } { + code {refresh(stop_transfer); +refresh(statusmsg); +Fl::check();} {} + } + decl {bool mustdisplaytimer;} {public + } + decl {bool polling;} {public + } + decl {Fl_Text_Buffer* catalogbuffer;} {public + } + Function {HD24UserInterface(int argc,char** argv,char* absprogpath)} {open + } { + code {control=new HD24control(); +control->parentui(this); +control->ready(0); +/*currpeakmode=0; +for (unsigned int i=0;irecorder=NULL; // will be initialized by make_window code +this->transeng=new hd24transferengine();} {} + } + Function {~HD24UserInterface()} {open + } { + code {if (control!=NULL) delete control; +if (portaudio!=NULL) delete portaudio; +if (soundfile!=NULL) delete soundfile; +if (libjack!=NULL) delete libjack; +if (currsong!=NULL) delete currsong; +if (currproj!=NULL) delete currproj; +if (currenthd24==defaulthd24) +{ + if (currenthd24!=NULL) delete currenthd24; +} else { + if (currenthd24!=NULL) delete currenthd24; + if (defaulthd24!=NULL) delete defaulthd24; +} +if (transeng!=NULL) +{ + delete transeng; + transeng=NULL; +}} {} + } + Function {confirm(const char* question)} {open return_type bool + } { + code {int result=fl_choice("%s","No","Yes",NULL,question); +if (result==1) { + return true; +} +return false;} {} + } + Function {samplerate()} {open return_type __uint32 + } { + code {// returns current samplerate of the UI, used by mixer +if (currsong==NULL) return 44100; +return currsong->samplerate();} {} + } + decl {friend class ScrubWheel;} {} + decl {int refreshingui;} {} + Function {saverestoretrackselection(Fl_Check_Button* o)} {open return_type void + } { + code {int i; +if (o->value()==1) +{ + if ( + (transfersource_mixleft->value() + +transfersource_mixright->value()) + ==1) + { + // save selected tracks + // disable track selection + // (repopulate formats list/file name/whatever?) + for (i=0;ivalue(); + track[i]->value(1); + track[i]->deactivate(); + button_invert_tracks->deactivate(); + } + fileformat->deactivate(); + return; + } +} + +if (o->value()==0) +{ + if ( + (transfersource_mixleft->value() + +transfersource_mixright->value()) + ==0) + { + // restore tracks + // enable track selection + for (i=0;ivalue(tracksave[i]); + track[i]->activate(); + button_invert_tracks->activate(); + + } + fileformat->activate(); + } +}} {} + } + Function {showprogtitle()} {open return_type void + } { + code {recorder->control->dispwrite(0,"HD24connect " + "HD24VERSION ",3000);} {} + } + decl {bool closingdown;} {public + } + Function {finish()} {open return_type void + } { + code {this->control->ready(0); +this->closingdown=true; +this->recorder->finish();} {} + } + Function {poll_callback(void* user)} {open return_type {static void} + } { + code {HD24UserInterface* mythis=(HD24UserInterface*)user; +//RecorderUI* mythis=(RecorderUI*)user; +\#if (HD24DEBUG==1) + //cout << "poll_callback" << endl; +\#endif +if (mythis->control->ready()!=1) { return; } + + +if (mythis->busy!=1) { + mythis->busy=1; + hd24song* mycurrsong=mythis->currsong; + + if (mythis->recorder->control->song()!=mythis->currsong) + { + mythis->recorder->control->song(mythis->currsong); /* tell recorder that the song is gone */ + } + + if (mycurrsong!=NULL) { + mycurrsong->bufferpoll(); + } + + + mythis->uiredrawcount=(mythis->uiredrawcount+1)%UIREFRESH; + if (mythis->uiredrawcount==0) { + + for (unsigned int i=0;iTabs->value()==mythis->tabCopyToPC) { +// if (mythis->trackpeak[i]>.01) { +// if (mythis->trackpeak[i]>.9) +// { +// mythis->trackled[i]->color(1); +// mythis->trackled[i]->redraw(); +// } else { +// if (mythis->trackpeak[i]>.7) { +// mythis->trackled[i]->color(3); +// mythis->trackled[i]->redraw(); +// } else { +// mythis->trackled[i]->color(2); +// mythis->trackled[i]->redraw(); +// } +// } +// } else { +// mythis->trackled[i]->color(52); +// mythis->trackled[i]->redraw(); +// } +// } + } + + if (mythis->Tabs->value()==mythis->tabMixer) { +// mythis->mixer->redraw(); + mythis->mixer->control->updatemeters(); + } + if (mythis->Tabs->value()==mythis->tabRecorder) { +// mythis->mixer->redraw(); +// mythis->recorder->control->updatemeters(); + } + // Fl check?? + } +} +if (mythis->recorder!=NULL) { + RecorderUI::poll_callback(mythis->recorder); +} +mythis->busy=0; +Fl::add_timeout(TIMEOUT,poll_callback,user);} {} + } + decl {Fl_Box* trackled[24];} {public + } + Function {setlocbuttonlabel(int i)} {open return_type void + } { + code {hd24song* locsong=this->currsong; +int numpoints=0; +if (locsong!=NULL) +{ + numpoints=locsong->locatepointcount(); +} +__uint32 locatepos=locsong->getlocatepos(i); +string* locname1=new string(""); + if (!(((i==0)||(i==numpoints)))) { + *locname1+="+"; + string* dur=locsong->display_duration(locatepos); + *locname1+=*dur; + delete (dur); + } else { + if (i!=0) + { + *locname1+="+"; + string* dur=locsong->display_duration(locatepos); + *locname1+=*dur; + delete (dur); + } else { + *locname1+="START"; + } + } + + *locname1="Seek to "+*locname1; + int l=strlen(locname1->c_str()); + for (i=0;ic_str()[i]; + locbuttonlabel[i+1]=(char)0; + } + + button_golocatepoint->label(&(this->locbuttonlabel[0])); + delete locname1;} {} + } + decl {char locbuttonlabel[64];} {} +} 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 @@ +# generated by Fast Light User Interface Designer (fluid) version 1.0107 +1 +-60 +REC +INP +-48 +-36 +-24 +-15 +-9 +-6 +-3 +-1 +CLIP +HD24connect +&File +&Detect HD24 drives +&Open drive image... +&Save drive image... +&Export catalog... +Save the disk directory to a printable text file +&Print catalog +Save the disk directory to a printable text file +&Recovery +&Select device... +Load &header file... +&Create header file... +Recover song from &power failure +E&xit +&Help +&About +Report a &Bug... +Request a &Feature... +&Credits +Transfer +Cancel +Drive +Drive name: +FS version: +Number of projects: +Rename... +Free space preview: +at +44100 +48000 +88200 +96000 +Hz, +2 +6 +8 +12 +16 +24 +tracks +Drive information +Drive contents +Project/Song +Song name: +Number of tracks: +Sample rate: +Bit depth: +Duration: +Rename... +Locate points: +Edit... +Write protected +Go +Number of songs: +Project name: +Rename... +Project information +Song information +Recorder +Play +Play +Play +Play +Play +arm +arm +Play +Play +Play +Play +Play +Play +Play +Play +Play +Play +Play +Play +Play +Play +Play +Play +SET LOC +Set Locate +AUTO LOOP +Auto Loop +Rewind +F Fwd +Stop +Play +LOOP START +Loop Start +LOOP END +Loop End +LOC 0 +Locate 0 +Record +arm +arm +arm +arm +arm +arm +arm +arm +arm +arm +arm +arm +arm +arm +arm +arm +arm +arm +arm +arm +arm +arm +arm +arm +Arm tracks +S +Solo +M +Mute +H +M +S +F +AUTO +PLAY +RTN +REC +REHEARSE +PITCH +REHEARSE +Set Locate +PUNCH IN +Set Locate +PUNCH OUT +Set Locate +Peak\012mode +arm +Peak\012clear +arm +Auto\012input +arm +All\012input +arm +Stereo input mapping +Normal +Swap Left and Right +Mix to mono +Use Left only +Use Right only +Mixer +Solo +Mute +S +Solo +M +Mute +MONO +MAIN +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +Copy to PC +Tracks: +Invert +01 +02 +03 +04 +05 +06 +07 +08 +09 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +Transfer +Browse... +Project dir: +From: +To: +Range... +Export file format: +Automatically limit size of exported files +When exporting multiple songs at once, prefix file names with song number +only if multiple songs have the same song name +Transfer source: +Transfer target: +Transfer options: +bytes +Note: The actual file size will be a rough approximation of the requested split size. +Stamp files with a custom sample rate +Sample rate: +44100 Hz +48000 Hz +88200 Hz +96000 Hz +User defined, specify --> +Hz +Split every: +650 MB (74 minute CD) +700 MB (80 minute CD) +1 GiB (Recommended for wave editors) +2 GiB (Max. legal WAV size) +4 GiB (Max. 32-bit limit) +4.7 GB (DVD size) +User defined, specify --> +Copy to HD24 +Transfer +01 +02 +03 +04 +05 +06 +07 +08 +09 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +Load... +Clear +font +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label +label 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 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0107 +header_name {.h} +code_name {.cxx} +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +class HD24TrackChannel {open : {public Fl_Group} +} { + decl {\#define PEAKMODE_NOHOLD 0} {public + } + decl {\#define PEAKMODE_TEMPHOLD 1} {public + } + decl {\#define PEAKMODE_CONTHOLD 2} {public + } + decl {\#define PEAKMODE_MAXHOLD 33} {public + } + decl {int mode;} {} + decl {int maxledslit; /* for peak hold */} {public + } + decl {int holdtime;} {public + } + decl {RecorderUI* ui;} {selected + } + decl {Fl_Box* levelled[10];} {public + } + decl {Fl_Window* win;} {} + decl {unsigned int channel;} {} + Function {make_window()} {open + } { + Fl_Window ledchannel {open + xywh {20 74 20 120} type Double color 0 labelcolor 7 + code0 {o->position(parent()->x(),parent()->y());} + class Fl_Group visible + } { + Fl_Box tracknum { + label 1 + xywh {3 76 12 6} box FLAT_BOX color 0 labelfont 1 labelsize 10 labelcolor 6 align 2 + } + Fl_Box led1 { + xywh {3 76 12 6} box FLAT_BOX color 6 labelfont 1 labelsize 10 labelcolor 6 align 2 hide + code0 {levelled[0]=led1;} + } + Fl_Box recled { + xywh {3 96 12 6} box FLAT_BOX color 1 labelfont 1 labelsize 10 labelcolor 1 align 2 hide + } + Fl_Box inputled { + xywh {3 104 12 6} box FLAT_BOX color 6 labelfont 1 labelsize 10 labelcolor 6 align 2 hide + } + Fl_Box led2 { + xywh {3 68 12 6} box FLAT_BOX color 6 labelfont 1 labelsize 10 labelcolor 6 align 2 hide + code0 {levelled[1]=led2;} + } + Fl_Box led3 { + xywh {3 60 12 6} box FLAT_BOX color 6 labelfont 1 labelsize 10 labelcolor 6 align 2 hide + code0 {levelled[2]=led3;} + } + Fl_Box led4 { + xywh {3 52 12 6} box FLAT_BOX color 6 labelfont 1 labelsize 10 labelcolor 6 align 2 hide + code0 {levelled[3]=led4;} + } + Fl_Box led5 { + xywh {3 44 12 6} box FLAT_BOX color 6 labelfont 1 labelsize 10 labelcolor 6 align 2 hide + code0 {levelled[4]=led5;} + } + Fl_Box led6 { + xywh {3 36 12 6} box FLAT_BOX color 6 labelfont 1 labelsize 10 labelcolor 6 align 2 hide + code0 {levelled[5]=led6;} + } + Fl_Box led7 { + xywh {3 28 12 6} box FLAT_BOX color 93 labelfont 1 labelsize 10 labelcolor 93 align 2 hide + code0 {levelled[6]=led7;} + } + Fl_Box led8 { + xywh {3 20 12 6} box FLAT_BOX color 93 labelfont 1 labelsize 10 labelcolor 93 align 2 hide + code0 {levelled[7]=led8;} + } + Fl_Box led9 { + xywh {3 12 12 6} box FLAT_BOX color 93 labelfont 1 labelsize 10 labelcolor 93 align 2 hide + code0 {levelled[8]=led9;} + } + Fl_Box led10 { + xywh {3 4 12 6} box FLAT_BOX color 1 labelfont 1 labelsize 10 labelcolor 1 align 2 hide + code0 {levelled[9]=led10;} + } + } + } + Function {setval(float levelval)} {open + } { + code {int lednum=0; +double myval=(double)levelval; + +// reset peaks if desired +switch (mode) { + case PEAKMODE_NOHOLD: this->peakreset(); break; + case PEAKMODE_TEMPHOLD: + if (this->holdtime>PEAKMODE_MAXHOLD) { + peakreset(); + } else { + this->holdtime++; + } + break; + case PEAKMODE_CONTHOLD: + break; + default: + this->mode=PEAKMODE_NOHOLD; + peakreset(); + break; +} + +int ledslit=0; + +if (myval>= ledlimit[lednum]) { ledslit=1; this->levelled[lednum++]->show(); } else { this->levelled[lednum++]->hide(); } +if (myval>= ledlimit[lednum]) { ledslit=2; this->levelled[lednum++]->show(); } else { this->levelled[lednum++]->hide(); } +if (myval>= ledlimit[lednum]) { ledslit=3; this->levelled[lednum++]->show(); } else { this->levelled[lednum++]->hide(); } +if (myval>= ledlimit[lednum]) { ledslit=4; this->levelled[lednum++]->show(); } else { this->levelled[lednum++]->hide(); } +if (myval>= ledlimit[lednum]) { ledslit=5; this->levelled[lednum++]->show(); } else { this->levelled[lednum++]->hide(); } +if (myval>= ledlimit[lednum]) { ledslit=6; this->levelled[lednum++]->show(); } else { this->levelled[lednum++]->hide(); } +if (myval>= ledlimit[lednum]) { ledslit=7; this->levelled[lednum++]->show(); } else { this->levelled[lednum++]->hide(); } +if (myval>= ledlimit[lednum]) { ledslit=8; this->levelled[lednum++]->show(); } else { this->levelled[lednum++]->hide(); } +if (myval>= ledlimit[lednum]) { ledslit=9; this->levelled[lednum++]->show(); } else { this->levelled[lednum++]->hide(); } +if (myval>= ledlimit[lednum]) { ledslit=10; this->levelled[lednum++]->show(); } else { this->levelled[lednum++]->hide(); } + +if (ledslit >this->maxledslit ) { + this->maxledslit=ledslit; + this->holdtime=0; +} else { + if ((this->maxledslit)>0) { + this->levelled[maxledslit-1]->show(); + } +} + +checkblink();} {} + } + Function {init_window()} {open return_type void + } { + code {this->mode=PEAKMODE_NOHOLD; +this->win=(Fl_Window*)make_window(); +this->ui=NULL; +this->channel=0; +this->maxledslit=0; +this->holdtime=0; +this->ledlimit[0]=(double)pow(10,(double)((double)-30/(double)10)); // -30 dB +this->ledlimit[1]=(double)pow(10,(double)((double)-24/(double)10)); // -24 dB +this->ledlimit[2]=(double)pow(10,(double)((double)-18/(double)10)); +this->ledlimit[3]=(double)pow(10,(double)((double)-12/(double)10)); //... +this->ledlimit[4]=(double)pow(10,(double)((double)-7.5/(double)10)); +this->ledlimit[5]=(double)pow(10,(double)((double)-4.5/(double)10)); +this->ledlimit[6]=(double)pow(10,(double)((double)-3/(double)10)); +this->ledlimit[7]=(double)pow(10,(double)((double)-1.5/(double)10)); +this->ledlimit[8]=(double)pow(10,(double)((double)-.5/(double)10)); +this->ledlimit[9]=(double)pow(10,(double)((double)0/(double)10)); // -0 dB + +this->setval(0); + +return;} {} + } + Function {HD24TrackChannel(int a,int b,int c,int d,const char* e):Fl_Group(a,b,c,d,e)} {open + } { + code {init_window();} {} + } + Function {HD24TrackChannel(int a,int b,int c,int d):Fl_Group(a,b,c,d,NULL)} {open + } { + code {init_window();} {} + } + Function {setchnum(__uint32 i)} {open + } { + code {/* As copy_label does not work on older versions of fltk, + the label now persists within the object but outside this + function. This solves the problem that is nowadays addressed + by copy_label, but without requiring an up-to-date version + of FLTK (1.1.6 or later). */ +channel=i; +snprintf(&labeltext[0],8,"%ld",i); +this->tracknum->label(labeltext);} {} + } + Function {setui(RecorderUI* p_ui)} {open + } { + code {this->ui=p_ui;} {} + } + Function {checkblink()} {open + } { + code {if (ui==NULL) return; +/* +TODO: Make available +if (ui->currenthd24==NULL) return; +*/ +if (channel==0) return; + + +bool showinputled=false; +/* +if (ui->currenthd24->isallinput()) { + if (ui->control->song()==NULL) { + // no song, show all input leds + showinputled=true; + } else { + // song selected, only show as many + // input leds as channels in the song + if (channel<=ui->control->song()->logical_channels()) { + showinputled=ui->control->song()->istrackmonitoringinput(channel); + } + } +} else { +*/ + if (ui->control->song()!=NULL) { + showinputled=ui->control->song()->istrackmonitoringinput(channel); + } +/* +} +*/ + +if (ui->control->song()!=NULL) { +if (ui->control->song()->logical_channels()recled->hide(); +} else { + if (ui->control->song()->trackarmed(channel)) { + if (ui->blinkcounter<8) { + this->recled->hide(); + } else { + this->recled->show(); + } + } else { + this->recled->hide(); + } +} +} +if (showinputled) { + this->inputled->show(); +} else { + this->inputled->hide(); +} + +return;} {} + } + decl {double ledlimit[10];} {} + Function {peakreset()} {return_type void + } { + code {maxledslit=0; +holdtime=0;} {} + } + Function {peakmode(int p_peakmode)} {return_type void + } { + code {this->mode=p_peakmode; +peakreset();} {} + } + decl {char labeltext[10];} {} +} + +class TrackInfo {: {public Fl_Group} +} { + Function {make_window()} {} { + Fl_Window ledchannel { + xywh {5 69 20 120} type Double color 0 labelcolor 7 align 16 hide + code0 {o->position(parent()->x(),parent()->y());} + class Fl_Group + } { + Fl_Box led1 { + label {-60} + xywh {3 76 12 6} box FLAT_BOX color 0 labelfont 1 labelsize 9 labelcolor 6 align 16 + } + Fl_Box recled { + label REC + xywh {3 96 12 6} box FLAT_BOX color 0 labelfont 1 labelsize 9 labelcolor 1 align 16 + } + Fl_Box inputled { + label INP + xywh {3 104 12 6} box FLAT_BOX color 0 labelfont 1 labelsize 9 labelcolor 6 align 16 + } + Fl_Box led2 { + label {-48} + xywh {3 68 12 6} box FLAT_BOX color 0 labelfont 1 labelsize 9 labelcolor 6 align 16 + } + Fl_Box led3 { + label {-36} + xywh {3 60 12 6} box FLAT_BOX color 0 labelfont 1 labelsize 9 labelcolor 6 align 16 + } + Fl_Box led4 { + label {-24} + xywh {3 52 12 6} box FLAT_BOX color 0 labelfont 1 labelsize 9 labelcolor 6 align 16 + } + Fl_Box led5 { + label {-15} + xywh {3 44 12 6} box FLAT_BOX color 0 labelfont 1 labelsize 9 labelcolor 1 align 16 + } + Fl_Box led6 { + label {-9} + xywh {3 36 12 6} box FLAT_BOX color 0 labelfont 1 labelsize 9 labelcolor 6 align 16 + } + Fl_Box led7 { + label {-6} + xywh {3 28 12 6} box FLAT_BOX color 0 labelfont 1 labelsize 9 labelcolor 93 align 16 + } + Fl_Box led8 { + label {-3} + xywh {3 20 12 6} box FLAT_BOX color 0 labelfont 1 labelsize 9 labelcolor 93 align 16 + } + Fl_Box led9 { + label {-1} + xywh {3 12 12 6} box FLAT_BOX color 0 labelfont 1 labelsize 9 labelcolor 93 align 16 + } + Fl_Box led10 { + label CLIP + xywh {0 4 22 6} box FLAT_BOX color 0 labelfont 1 labelsize 8 labelcolor 1 align 16 + } + } + } + Function {TrackInfo(int a,int b,int c,int d,const char* e):Fl_Group(a,b,c,d,e)} {open + } { + code {make_window();} {} + } + Function {TrackInfo(int a,int b,int c,int d):Fl_Group(a,b,c,d,NULL)} {open + } { + code {make_window();} {} + } +} 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 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0107 +header_name {.h} +code_name {.cxx} +class UserInterface_HelpAbout {open +} { + Function {make_window()} {open + } { + Fl_Window {} { + label {About HD24connect} open + xywh {567 209 340 350} type Double color 52 modal visible + } { + Fl_Box {} { + xywh {10 10 320 305} box DOWN_BOX color 7 + } + Fl_Box {} { + image {images/hd24connect.png} xywh {45 25 250 77} + } + Fl_Button {} { + label OK + callback {/* Find the window regardless of its class name */ +Fl_Window * x=Fl::first_window(); +x->~Fl_Window();} + xywh {125 320 90 25} labelsize 12 + } + Fl_Box {} { + label {HD24connect version HD24VERSION} + xywh {45 110 250 20} labelsize 12 + } + Fl_Box {} { + label {This program was written as an independent effort,} + xywh {15 130 305 20} labelsize 11 + } + Fl_Box {} { + label {and is neither endorsed by nor affiliated with Alesis.} + xywh {15 145 305 20} labelsize 11 + } + Fl_Box {} { + label {No warranty of any kind is given or implied.} selected + xywh {15 175 305 20} labelsize 11 + } + Fl_Box {} { + label {Share and enjoy!} + xywh {10 290 310 20} labelsize 11 + } + Fl_Box {} { + label {Use at your own risk.} + xywh {15 190 305 20} labelsize 11 + } + Fl_Box {} { + label {If you find this program useful, please make a } + xywh {15 215 305 20} labelsize 11 + } + Fl_Box {} { + label {donation to the author. See } + xywh {15 230 305 20} labelsize 11 + } + Fl_Box {} { + label {http://ringbreak.dnd.utwente.nl/~mrjb/hd24tools/} + xywh {15 245 305 20} labelsize 11 + } + Fl_Box {} { + label {Feel free to request additional features.} + xywh {15 260 305 20} labelsize 11 + } + } + } +} 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 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0109 +header_name {.h} +code_name {.cxx} +decl {\#define MAXSAMRATE 48000} {public +} + +decl {\#define maxfilterunits 200} {public +} + +decl {\#define maxreverbunits 20} {public +} + +decl {\#define maxreverbseconds 1} {public +} + +decl {\#define eqperchan 4} {public +} + +decl {\#define Pi2 (2*3.1415926535897)} {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +class stereosample {open +} { + decl {float left;} {public + } + decl {float right;} {public + } +} + +decl {class MixerChannelControl;} {public +} + +decl {class MixerChannelUI;} {public +} + +decl {class MixerChannelData;} {public +} + +decl {class MasterChannelUI;} {public +} + +decl {class MasterChannelControl;} {public +} + +decl {class MixerControl;} {public +} + +decl {class MixerChannelUI;} {public +} + +class MixerLevelMeterData {} { + decl {\#define PEAKMODE_NOHOLD 0} {public + } + decl {\#define PEAKMODE_TEMPHOLD 1} {public + } + decl {\#define PEAKMODE_CONTHOLD 2} {public + } + decl {\#define PEAKMODE_MAXHOLD 33} {public + } + decl {int mode;} {public + } + decl {double dB;} {public + } + decl {double peakvalue; /* for peak hold */} {public + } + decl {double metervalue;} {public + } + decl {int holdtime;} {public + } + decl {int dBrange;} {public + } +} + +class MixerLevelMeterControl {} { + decl {MixerLevelMeterData* data;} {} + Function {MixerLevelMeterControl()} {open + } { + code {data=new MixerLevelMeterData; +init();} {} + } + Function {~MixerLevelMeterControl()} {open + } { + code {delete data;} {} + } + Function {setvalue(double levelval)} {open + } { + code {data->dB=20*log10(levelval); +return; + +// reset peaks if desired +switch (data->mode) { + case PEAKMODE_NOHOLD: this->peakreset(); break; + case PEAKMODE_TEMPHOLD: + if (data->holdtime>PEAKMODE_MAXHOLD) { + peakreset(); + } else { + data->holdtime++; + } + break; + case PEAKMODE_CONTHOLD: + break; + default: + data->mode=PEAKMODE_NOHOLD; + peakreset(); + break; +} + +if (levelval>data->metervalue) { + data->peakvalue=data->metervalue; + data->holdtime=0; +}} {} + } + Function {peakmode(int p_peakmode)} {open return_type void + } { + code {data->mode=p_peakmode; +peakreset();} {} + } + Function {peakreset()} {open return_type void + } { + code {data->peakvalue=0; +data->holdtime=0;} {} + } + Function {init()} {open return_type void + } { + code {data->peakvalue=0; +data->holdtime=0; + +data->dBrange=60; +this->setvalue(0); +return;} {} + } + Function {getpctvalue()} {open return_type float + } { + code {float pct=100-(100*(-(data->dB)/(data->dBrange))); + +if (pct<0) { pct=0; } +if (pct>100) { pct=100; } + +return pct;} {} + } +} + +class MixerLevelMeterUI {: {public Fl_Group} +} { + decl {MixerLevelMeterControl* control;} {public + } + Function {MixerLevelMeterUI(int a,int b,int c,int d,const char* e):Fl_Group(a,b,c,d,e)} {} { + code {init_ui();} {} + } + Function {MixerLevelMeterUI(int a,int b,int c,int d):Fl_Group(a,b,c,d,NULL)} {} { + code {init_ui();} {} + } + Function {init_ui()} {open private + } { + code {this->control=new MixerLevelMeterControl();} {} + } + Function {draw()} {open + } { + code {float pct=(control->getpctvalue())/100; + +int zro=y(); +int bot=zro+128; +int myx=x(); +int top=bot- ((int)( pct*128)); + + fl_color(fl_rgb_color(0,255,0)); + fl_line(myx,top,myx,bot); + myx++; + fl_line(myx,top,myx,bot); + myx--; + + fl_color(fl_rgb_color(0,0,0)); + fl_line(myx,zro,myx,top); + myx++; + fl_line(myx,zro,myx,top); + +return;} {} + } + Function {~MixerLevelMeterUI()} {open + } { + code {delete control;} {} + } +} + +class MixerChannelData {open +} { + decl {int bypass; /* 1 to bypass all mixing */} {public + } + decl {friend class MixerChannelUI;} {} + decl {friend class MixerChannelControl;} {} + decl {MixerChannelUI* parentui;} {} + decl {double trackpeak;} {public + } + decl {int enable_eq; /* overall eq settings */} {public + } + decl {int enable_pan; /* overall eq settings */} {public + } + decl {int eq_on[eqperchan];} {public + } + decl {double eq_gain[eqperchan];} {public + } + decl {double eq_freq[eqperchan];} {public + } + decl {double eq_Q[eqperchan];} {public + } + decl {double eq_type[eqperchan];} {public + } + decl {double fadermult;} {public + } + decl {double faderval;} {public + } + decl {double panvalue;} {public + } + decl {float* delaybuffer;} {} + decl {long delaybuffersize;} {public + } + decl {long delaybuffersam;} {public + } + decl {int solo;} {} + decl {int mute;} {} + decl {int ch_number;} {} + decl {char strchnum[4];} {} + decl {float* sample;} {public + } + decl {int mixmono;} {} + decl {MixerControl* parentmixercontrol;} {} + decl {__uint32 samplerate;} {public + } + decl {int selected;} {} + decl {int ringbufpos[maxreverbunits];} {} +} + +class MixerChannelControl {open +} { + decl {friend class MixerChannelUI;} {} + decl {friend class MixerChannelData;} {} + decl {MixerChannelData* data;} {public + } + Function {init()} {open return_type void + } { + code {data->bypass=0; +data->trackpeak=0; +data->enable_eq=1; +data->enable_pan=1; +data->solo=0; +data->mute=0; +data->sample=(float *)malloc(24000*sizeof(float)); +data->eq_gain[0]=0; +data->eq_gain[1]=0; +data->eq_gain[2]=0; +data->eq_gain[3]=0; +data->eq_Q[0]=1; +data->eq_Q[1]=1; +data->eq_Q[2]=1; +data->eq_Q[3]=1; +data->eq_on[0]=1; +data->eq_on[1]=1; +data->eq_on[2]=1; +data->eq_on[3]=1; +data->eq_freq[0]=100; +data->eq_freq[1]=600; +data->eq_freq[2]=1600; +data->eq_freq[3]=6000; +data->samplerate=44100; // TODO: set to proper val +data->faderval=90; +data->fadermult=1; +data->panvalue=0; + + +data->delaybuffersize=maxreverbunits*maxreverbseconds*MAXSAMRATE; +data->delaybuffer=(float *)malloc(sizeof(float)*(data->delaybuffersize)); +if (data->delaybuffer==NULL) cout << " out of mem L" << endl; +data->delaybuffersam=data->delaybuffersize; +for (int i=0;idelaybuffersize;i++) +{ + data->delaybuffer[i]=0; +} +data->ringbufpos[0]=881; +data->ringbufpos[1]=883; +data->ringbufpos[2]=887; +data->ringbufpos[3]=907; +data->ringbufpos[4]=911; +data->ringbufpos[5]=919; +data->ringbufpos[6]=929; +data->ringbufpos[7]=937; +data->ringbufpos[8]=941; +data->ringbufpos[9]=947; +data->ringbufpos[10]=953; +data->ringbufpos[11]=967; +data->ringbufpos[12]=971; +data->ringbufpos[13]=977; +data->ringbufpos[14]=983; +data->ringbufpos[15]=991; +data->ringbufpos[16]=997; +data->ringbufpos[17]=1009; +data->ringbufpos[18]=1013; +data->ringbufpos[19]=1019; + +return;} {} + } + Function {MixerChannelControl()} {open + } { + code {data=new MixerChannelData(); +init();} {} + } + Function {~MixerChannelControl()} {open + } { + code {free (data->sample); +data->sample=NULL; +free (data->delaybuffer); +data->delaybuffer=NULL; +delete data; +data=NULL;} {} + } + Function {fadervalue(const double p_val)} {} { + code {double lin; +if (p_val == 0) { + lin=0; +} else { + lin=pow(10,(p_val-90)/60); +} +data->fadermult=lin; +data->faderval=p_val; +data->parentui->fader->value(p_val); +data->parentui->redraw();} {} + } + Function {fadervalue()} {open return_type double + } { + code {return data->faderval;} {} + } + Function {updatemeters()} {open return_type void + } { + code {// update and redraw meterlevels object +this->parentui()->mixled->control->setvalue(data->trackpeak); +this->parentui()->mixled->redraw(); +// then, reset peak value +trackpeak(0);} {} + } + Function {solo(int p_val)} {open return_type void + } { + code {data->solo=p_val; +data->parentui->mixsolo->value(p_val); +data->parentui->mixsolo->damage(); +data->parentui->mixsolo->redraw(); +if (p_val==1) +{ +this->parentmixercontrol()->selectedchannel(this->channel_number()-1); +}} {} + } + Function {mute(int p_val)} {open return_type void + } { + code {data->mute=p_val; +data->parentui->mixmute->value(p_val); +data->parentui->mixmute->damage(); +data->parentui->mixmute->redraw(); +//if (ui!=NULL) { +// ui->readmixer(); +//}} {} + } + Function {solo()} {open return_type int + } { + code {return data->solo;} {} + } + Function {mute()} {open return_type int + } { + code {return data->mute;} {} + } + Function {issolo()} {open return_type int + } { + code {return data->solo;} {} + } + Function {ismute()} {open return_type int + } { + code {return data->mute;} {} + } + Function {getfadermult()} {open return_type double + } { + code {return data->fadermult;} {} + } + Function {trackpeak()} {open return_type double + } { + code {return data->trackpeak;} {} + } + Function {trackpeak(double peakval)} {open return_type void + } { + code {data->trackpeak=peakval;} {} + } + Function {channel_number(int ch)} {open return_type void + } { + code {data->ch_number=ch; +snprintf(data->strchnum,3,"%d",ch); +data->parentui->mixmute->label(data->strchnum);} {} + } + Function {channel_number()} {open return_type int + } { + code {return data->ch_number;} {} + } + Function {parentmixercontrol(MixerControl* p_parentmixercontrol)} {open return_type void + } { + code {data->parentmixercontrol=p_parentmixercontrol;} {} + } + Function {parentui(MixerChannelUI* p_parentui)} {open return_type void + } { + code {data->parentui=p_parentui;} {} + } + Function {parentui()} {open return_type {MixerChannelUI*} + } { + code {return data->parentui;} {} + } + Function {parentmixercontrol()} {open return_type {MixerControl*} + } { + code {return data->parentmixercontrol;} {} + } + Function {panvalue(const double p_val)} {open + } { + code {data->panvalue=p_val; +data->parentui->mixpan->value(p_val); +data->parentui->mixpan->damage(); +data->parentui->mixpan->redraw();} {} + } + Function {panvalue()} {open return_type double + } { + code {return data->panvalue;} {} + } + Function {sample(int framenum,float samval)} {open + } { + code {if (data==NULL) return; +if ((data->sample)==NULL) return; +data->sample[framenum]=samval; +/*float q=1; +if (samval<0) { + q=-1; +} +if ((samval*q) > data->trackpeak) { + data->trackpeak=samval*q; +}*/} {} + } + Function {sample(int framenum)} {return_type float + } { + code {return data->sample[framenum];} {} + } + Function {getsample(stereosample* sam,int framenum)} {open return_type void + } { + code {float monosam=data->sample[framenum]; + +if (data->bypass==1) +{ + /* Bypass all mixer functions, just return the sample */ + sam->left=monosam/2; + sam->right=monosam/2; + return; +} + +float panval; +if (data->enable_eq==1) { + int Q=1; + // FilterCell(unsigned long Unit, double Input, double Frequency, double Q, double Gain, unsigned long Type) + if (eq_on(0)==1 && (eq_gain(0)!=0)) monosam=FilterCell(0,monosam,eq_freq(0),Q,eq_gain(0),7); + if (eq_on(1)==1 && (eq_gain(1)!=0)) monosam=FilterCell(1,monosam,eq_freq(1),Q,eq_gain(1),7); + if (eq_on(2)==1 && (eq_gain(2)!=0)) monosam=FilterCell(2,monosam,eq_freq(2),Q,eq_gain(2),7); + if (eq_on(3)==1 && (eq_gain(3)!=0)) monosam=FilterCell(3,monosam,eq_freq(3),Q,eq_gain(3),7); +} + +monosam*=getfadermult(); + +sam->left=monosam; +sam->right=monosam; + +if (data->enable_pan==1) +{ + panval=panvalue(); +} else { + panval=0; +} + +float pctright=(panval+127)/254; +float pctleft=1-pctright; +sam->left*=pctleft; +sam->right*=pctright; + +float subsamval=fabs(monosam); +if (subsamval > trackpeak()) { + trackpeak(subsamval); +} + +return;} {} + } + Function {channelselect(int select)} {return_type void + } { + code {data->selected=select; +parentui()->mixchsel->value(select); +parentui()->mixchsel->redraw();} {} + } + Function {FilterCell(unsigned long Unit, double Input, double Frequency, double Q, double Gain, unsigned long Type)} {return_type double + } { + code {__uint32 SampleRate=data->samplerate; + +/* --------------------------------------------------------------- */ + double Output,S,omega,A,sn,cs,alpha,beta,temp1,temp2,temp3,temp4; + Output=Input; + +/* -- check if frequency, Q, gain or type has changed.. and, if so, update coefficients */ + if ( ( Frequency != filter_f[Unit] ) || ( Gain != filter_g[Unit] ) || ( Q != filter_q[Unit] ) || ( Type != filter_t[Unit] ) ) { + filter_f[Unit] = Frequency; filter_q[Unit] = Q; filter_g[Unit] = Gain; filter_t[Unit] = Type; /* remember last frequency, q, gain and type */ + switch (Type) { + case 0: /* no filtering */ + filter_b0[Unit] = pow( 10.0, Gain / 20.0 ); /* convert from dB to linear */ + break; + case 1: /* lowpass */ + Gain = pow( 10.0, Gain / 20.0 ); /* convert from dB to linear */ + omega = ( Pi2 * Frequency ) / SampleRate; + sn = sin( omega ); cs = cos( omega ); + alpha = sn / ( 2.0 * Q ); + filter_a0[Unit] = 1.0 / ( 1.0 + alpha ); + filter_a1[Unit] = ( -2.0 * cs ) * filter_a0[Unit]; + filter_a2[Unit] = ( 1.0 - alpha ) * filter_a0[Unit]; + filter_b1[Unit] = ( 1.0 - cs ) * filter_a0[Unit] * Gain; + filter_b0[Unit] = filter_b1[Unit] * 0.5; + break; + case 2: /* highpass */ + Gain = pow( 10.0, Gain / 20.0 ); /* convert from dB to linear */ + omega = ( Pi2 * Frequency ) / SampleRate; + sn = sin( omega ); cs = cos( omega ); + alpha = sn / ( 2.0 * Q ); + filter_a0[Unit] = 1.0 / ( 1.0 + alpha ); + filter_a1[Unit] = ( -2.0 * cs ) * filter_a0[Unit]; + filter_a2[Unit] = ( 1.0 - alpha ) * filter_a0[Unit]; + filter_b1[Unit] = -( 1.0 + cs ) * filter_a0[Unit] * Gain; + filter_b0[Unit] = -filter_b1[Unit] * 0.5; + break; + case 3: /* bandpass */ + Gain = pow( 10.0, Gain / 20.0 ); /* convert from dB to linear */ + omega = ( Pi2 * Frequency ) / SampleRate; + sn = sin( omega ); cs = cos( omega ); + alpha = sn / ( 2.0 * Q ); + filter_a0[Unit] = 1.0 / ( 1.0 + alpha ); + filter_a1[Unit] = ( -2.0 * cs ) * filter_a0[Unit]; + filter_a2[Unit] = ( 1.0 - alpha ) * filter_a0[Unit]; + filter_b0[Unit] = alpha * filter_a0[Unit] * Gain; + break; + case 4: /* notch */ + Gain = pow( 10.0, Gain / 20.0 ); /* convert from dB to linear */ + omega = ( Pi2 * Frequency ) / SampleRate; + sn = sin( omega ); cs = cos( omega ); + alpha = sn / ( 2.0 * Q ); + filter_a0[Unit] = 1.0 / ( 1.0 + alpha ); + filter_a1[Unit] = ( -2.0 * cs ) * filter_a0[Unit]; + filter_a2[Unit] = ( 1.0 - alpha ) * filter_a0[Unit]; + filter_b0[Unit] = filter_a0[Unit] * Gain; + filter_b1[Unit] = filter_a1[Unit] * Gain; + break; + case 5: /* lowshelf */ + /* "shelf slope" 1.0 = max slope, because neither Q nor bandwidth is used in */ + /* those filters (note: true only for lowshelf and highshelf, not peaking). */ + S = 1.0; /* used only by lowshelf and highshelf */ + A = pow( 10.0 , ( Gain / 40.0 ) ); /* Gain is expressed in dB */ + omega = ( Pi2 * Frequency ) / SampleRate; + sn = sin( omega ); cs = cos( omega ); + temp1 = A + 1.0; temp2 = A - 1.0; temp3 = temp1 * cs; temp4 = temp2 * cs; + beta = sn * sqrt( ( A * A + 1.0 ) / S - temp2 * temp2 ); + filter_a0[Unit] = 1.0 / ( temp1 + temp4 + beta ); + filter_a1[Unit] = ( -2.0 * ( temp2 + temp3 ) ) * filter_a0[Unit]; + filter_a2[Unit] = ( temp1 + temp4 - beta ) * filter_a0[Unit]; + filter_b0[Unit] = ( A * ( temp1 - temp4 + beta ) ) * filter_a0[Unit]; + filter_b1[Unit] = ( 2.0 * A * ( temp2 - temp3 ) ) * filter_a0[Unit]; + filter_b2[Unit] = ( A * ( temp1 - temp4 - beta ) ) * filter_a0[Unit]; + break; + case 6: /* highshelf */ + /* "shelf slope" 1.0 = max slope, because neither Q nor bandwidth is used in */ + /* those filters (note: true only for lowshelf and highshelf, not peaking). */ + S = 1.0; /* used only by lowshelf and highshelf */ + A = pow( 10.0, ( Gain / 40.0 ) ); /* Gain is expressed in dB */ + omega = ( Pi2 * Frequency ) / SampleRate; + sn = sin( omega ); cs = cos( omega ); + temp1 = A + 1.0; temp2 = A - 1.0; temp3 = temp1 * cs; temp4 = temp2 * cs; + beta = sn * sqrt( ( A * A + 1.0 ) / S - temp2 * temp2 ); + filter_a0[Unit] = 1.0 / ( temp1 - temp4 + beta ); + filter_a1[Unit] = ( 2.0 * ( temp2 - temp3 ) ) * filter_a0[Unit]; + filter_a2[Unit] = ( temp1 - temp4 - beta ) * filter_a0[Unit]; + filter_b0[Unit] = ( A * ( temp1 + temp4 + beta ) ) * filter_a0[Unit]; + filter_b1[Unit] = ( -2.0 * A * ( temp2 + temp3 ) ) * filter_a0[Unit]; + filter_b2[Unit] = ( A * ( temp1 + temp4 - beta ) ) * filter_a0[Unit]; + break; + case 7: /* peaking */ + A = pow( 10.0, ( Gain / 40.0 ) ); /* Gain is expressed in dB */ + omega = ( Pi2 * Frequency ) / SampleRate; + sn = sin( omega ); cs = cos( omega ); + alpha = sn / ( 2.0 * Q ); + temp1 = alpha * A; + temp2 = alpha / A; + filter_a0[Unit] = 1.0 / ( 1.0 + temp2 ); + filter_a1[Unit] = ( -2.0 * cs ) * filter_a0[Unit]; + filter_a2[Unit] = ( 1.0 - temp2 ) * filter_a0[Unit]; + filter_b0[Unit] = ( 1.0 + temp1 ) * filter_a0[Unit]; + filter_b2[Unit] = ( 1.0 - temp1 ) * filter_a0[Unit]; + break; + } + } +/* -- filter loop: if you don't change the parameters of the filter dynamically, ~only this code will be executed. */ + switch (Type) { + case 0: /* no filtering */ + Output = filter_b0[Unit]*Input; + break; + case 1: /* lowpass */ + case 2: /* highpass */ + Output = filter_b0[Unit]*Input + + filter_b1[Unit]*filter_i1[Unit] + + filter_b0[Unit]*filter_i2[Unit] + - filter_a1[Unit]*filter_o1[Unit] + - filter_a2[Unit]*filter_o2[Unit]; + break; + case 3: /* bandpass */ + Output = filter_b0[Unit]*Input + - filter_b0[Unit]*filter_i2[Unit] + - filter_a1[Unit]*filter_o1[Unit] + - filter_a2[Unit]*filter_o2[Unit]; + break; + case 4: /* notch */ + Output = filter_b0[Unit]*Input + + filter_b1[Unit]*filter_i1[Unit] + + filter_b0[Unit]*filter_i2[Unit] + - filter_a1[Unit]*filter_o1[Unit] + - filter_a2[Unit]*filter_o2[Unit]; + break; + case 5: /* low shelving */ + case 6: /* high shelving */ + Output = filter_b0[Unit]*Input + + filter_b1[Unit]*filter_i1[Unit] + + filter_b2[Unit]*filter_i2[Unit] + - filter_a1[Unit]*filter_o1[Unit] + - filter_a2[Unit]*filter_o2[Unit]; + break; + case 7: /* peaking */ + Output = filter_b0[Unit]*Input + + filter_a1[Unit]*filter_i1[Unit] + + filter_b2[Unit]*filter_i2[Unit] + - filter_a1[Unit]*filter_o1[Unit] + - filter_a2[Unit]*filter_o2[Unit]; + break; + } + filter_o2[Unit]=filter_o1[Unit]; + filter_o1[Unit]=Output; + filter_i2[Unit]=filter_i1[Unit]; + filter_i1[Unit]=Input; /* update variables for recursion */ + + return(Output);} {} + } + Function {eq_gain(int whicheq,double gain)} {open return_type void + } { + code {if (whicheq>4) return; +if (whicheq<0) return; +data->eq_gain[whicheq]=gain; + + +//cout << "set freq to "<parentui()->gain1; + dispwidget=parentmixercontrol()->parentui()->dispgain1; + break; + } + case 1: + { + gainwidget=parentmixercontrol()->parentui()->gain2; + dispwidget=parentmixercontrol()->parentui()->dispgain2; + break; + } + case 2: + { + gainwidget=parentmixercontrol()->parentui()->gain3; + dispwidget=parentmixercontrol()->parentui()->dispgain3; + break; + } + case 3: + { + gainwidget=parentmixercontrol()->parentui()->gain4; + dispwidget=parentmixercontrol()->parentui()->dispgain4; + break; + } +} +if (dispwidget!=NULL) +{ + string* sval=Convert::int64tostr((__sint64)gain); + dispwidget->value(sval->c_str()); + delete sval; + dispwidget->redraw(); +} +if (gainwidget!=NULL) +{ + gainwidget->value(gain); + gainwidget->redraw(); +}} {} + } + Function {eq_gain(int whicheq)} {open return_type double + } { + code {if (whicheq>4) return 0; +if (whicheq<0) return 0; +return data->eq_gain[whicheq];} {} + } + Function {eq_freq(int whicheq,double freq)} {open return_type void + } { + code {if (whicheq>4) return; +if (whicheq<0) return; +data->eq_freq[whicheq]=freq; +//cout << "set freq to "<parentui()->freq1; + dispwidget=parentmixercontrol()->parentui()->dispfreq1; + break; + } + case 1: + { + freqwidget=parentmixercontrol()->parentui()->freq2; + dispwidget=parentmixercontrol()->parentui()->dispfreq2; + break; + } + case 2: + { + freqwidget=parentmixercontrol()->parentui()->freq3; + dispwidget=parentmixercontrol()->parentui()->dispfreq3; + break; + } + case 3: + { + freqwidget=parentmixercontrol()->parentui()->freq4; + dispwidget=parentmixercontrol()->parentui()->dispfreq4; + break; + } +} +if (dispwidget!=NULL) +{ + string* sval=Convert::int64tostr((__sint64)freq); + dispwidget->value(sval->c_str()); + delete sval; + dispwidget->redraw(); +} +if (freqwidget!=NULL) +{ + freqwidget->value(freq); + freqwidget->redraw(); +}} {} + } + Function {eq_freq(int whicheq)} {return_type double + } { + code {if (whicheq>4) return 0; +if (whicheq<0) return 0; +return data->eq_freq[whicheq];} {} + } + Function {eq_on(int whicheq,int onoff)} {return_type void + } { + code {if (whicheq>4) return; +if (whicheq<0) return; +data->eq_on[whicheq]=onoff; + +switch (whicheq) { + case 0: parentmixercontrol()->parentui()->eqon1->value(onoff); break; + case 1: parentmixercontrol()->parentui()->eqon2->value(onoff); break; + case 2: parentmixercontrol()->parentui()->eqon3->value(onoff); break; + case 3: parentmixercontrol()->parentui()->eqon4->value(onoff); break; +} +parentmixercontrol()->parentui()->eqon1->redraw(); +parentmixercontrol()->parentui()->eqon2->redraw(); +parentmixercontrol()->parentui()->eqon3->redraw(); +parentmixercontrol()->parentui()->eqon4->redraw();} {} + } + Function {eq_on(int whicheq)} {return_type int + } { + code {if (whicheq>4) return 0; +if (whicheq<0) return 0; +return data->eq_on[whicheq];} {} + } + Function {eq_Q(int whicheq,double Q)} {return_type void + } { + code {if (whicheq>4) return; +if (whicheq<0) return; +data->eq_Q[whicheq]=Q; +//cout << "set freq to "<parentui()->Q1->value(freq); break; +// case 1: parentmixercontrol()->parentui()->Q2->value(freq); break; +// case 2: parentmixercontrol()->parentui()->Q3->value(freq); break; +// case 3: parentmixercontrol()->parentui()->Q4->value(freq); break; +//} +//parentmixercontrol()->parentui()->freq1->redraw(); +//parentmixercontrol()->parentui()->freq2->redraw(); +//parentmixercontrol()->parentui()->freq3->redraw(); +//parentmixercontrol()->parentui()->freq4->redraw();} {} + } + Function {eq_Q(int whicheq)} {return_type double + } { + code {if (whicheq>4) return 0; +if (whicheq<0) return 0; +return data->eq_Q[whicheq];} {} + } + decl {double filter_i1[eqperchan]; /* temporary variables */} {} + decl {double filter_i2[eqperchan];} {} + decl {double filter_o1[eqperchan];} {} + decl {double filter_o2[eqperchan];} {} + decl {double filter_a0[eqperchan]; /*coefficients */} {} + decl {double filter_a1[eqperchan];} {} + decl {double filter_a2[eqperchan];} {} + decl {double filter_b0[eqperchan]; /*coefficients */} {} + decl {double filter_b1[eqperchan];} {} + decl {double filter_b2[eqperchan];} {} + decl {double filter_f[eqperchan]; /* last freq used */} {} + decl {double filter_q[eqperchan]; /* last Q used */} {} + decl {double filter_g[eqperchan]; /* last gain used */} {} + decl {unsigned long filter_t[eqperchan]; /* last T used */} {} + Function {pan_enabled(int yesno)} {open return_type void + } { + code {data->enable_pan=yesno;} {} + } + Function {pan_enabled()} {open return_type int + } { + code {return data->enable_pan;} {} + } + Function {eq_enabled(int yesno)} {return_type void + } { + code {data->enable_eq=yesno;} {} + } + Function {eq_enabled()} {open return_type int + } { + code {return data->enable_eq;} {} + } + Function {bypass(int yesno)} {open return_type void + } { + code {data->bypass=yesno;} {} + } + Function {bypass()} {open return_type int + } { + code {return data->bypass;} {} + } + Function {samplerate(__uint32 p_samplerate)} {open return_type void + } { + code {data->samplerate=p_samplerate;} {} + } + Function {samplerate()} {open return_type __uint32 + } { + code {return data->samplerate;} {} + } +} + +class MixerChannelUI {open : {public Fl_Group} +} { + decl {MixerChannelControl* control;} {public + } + Function {MixerChannelUI(int a,int b,int c,int d,const char* e):Fl_Group(a,b,c,d,e)} {open + } { + code {init_ui();} {} + } + Function {MixerChannelUI(int a,int b,int c,int d):Fl_Group(a,b,c,d,NULL)} {open + } { + code {init_ui();} {} + } + Function {init_ui()} {open private + } { + code {this->control=new MixerChannelControl(); +this->control->parentui(this); +make_window();} {} + } + Function {make_window()} {open + } { + Fl_Window channelstrip {open + xywh {698 377 20 235} type Double + code0 {o->position(this->x(),this->y());} + class Fl_Group visible + } { + Fl_Group resources {open + xywh {80 62 150 98} hide deactivate + } { + Fl_Button button_mute_up { + tooltip Play image {images/button_mute.gif} xywh {80 62 5 13} labelsize 11 align 16 deactivate + } + Fl_Button button_mute_dn { + tooltip Play image {images/button_mute_dn.gif} xywh {85 62 35 13} labelsize 11 align 16 deactivate + } + Fl_Button button_solo_up { + tooltip Play image {images/button_solo.gif} xywh {80 62 5 13} labelsize 11 align 16 deactivate + } + Fl_Button button_solo_dn { + tooltip Play image {images/button_solo_dn.gif} xywh {85 62 45 13} labelsize 11 align 16 deactivate + } + } + Fl_Button mixmute { + label 1 + callback {//mute(0,o->value()); +this->control->mute(o->value());} + tooltip Mute xywh {0 65 20 15} selection_color 1 labelfont 1 labelsize 10 align 2 + code0 {o->up_image(button_mute_up->image()); o->down_image(button_mute_dn->image());} + class Fl_Image_Toggle_Button + } + Fl_Button mixsolo { + callback {this->control->solo(o->value());} + tooltip Solo xywh {0 45 20 15} selection_color 2 + code0 {o->up_image(button_solo_up->image()); o->down_image(button_solo_dn->image());} + class Fl_Image_Toggle_Button + } + Fl_Dial mixpan { + callback {control->panvalue(o->value());} + xywh {0 25 20 20} minimum -127 maximum 127 step 1 + class WidgetPDial + } + Fl_Round_Button mixchsel { + callback {this->control->parentmixercontrol()->selectedchannel(this->control->channel_number()-1);} + xywh {0 0 15 20} down_box ROUND_DOWN_BOX align 2 + } + Fl_Group mixled {open + xywh {18 93 4 132} + class MixerLevelMeterUI + } {} + Fl_Slider fader { + callback {control->fadervalue(o->value());} + 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 + code0 {o->clear_visible_focus();} + } + } + } + Function {~MixerChannelUI()} {open + } { + code {delete control;} {} + } +} + +class MasterChannelData {open +} { + decl {friend class MasterChannelUI;} {} + decl {friend class MasterChannelControl;} {} + decl {MasterChannelUI* parentui;} {} + decl {double trackpeak[2];} {public + } + decl {int eq_on[eqperchan];} {public + } + decl {double eq_gain[eqperchan];} {public + } + decl {double eq_freq[eqperchan];} {public + } + decl {double eq_Q[eqperchan];} {public + } + decl {double eq_type[eqperchan];} {public + } + decl {double fadermult[2];} {public + } + decl {double fadervalue;} {public + } + decl {double panvalue;} {public + } + decl {float* delaybuffer;} {} + decl {long delaybuffersize;} {public + } + decl {long delaybuffersam;} {public + } + decl {int solo;} {} + decl {int mute;} {} + decl {int ch_number;} {} + decl {char strchnum[4];} {} + decl {float* sample;} {public + } + decl {int mixmono;} {} +} + +class MasterChannelControl {open +} { + decl {friend class MasterChannelUI;} {} + Function {init()} {open return_type void + } { + code {data->solo=0; +data->mute=0; +data->mixmono=0; +data->sample=(float *)malloc(24000*sizeof(float)); +data->trackpeak[0]=0; +data->trackpeak[1]=0; +data->fadermult[0]=1; +data->fadermult[1]=1; +data->panvalue=0; +data->fadervalue=90; +return;} {} + } + decl {MasterChannelData* data;} {} + Function {MasterChannelControl()} {open + } { + code {data=new MasterChannelData; +init();} {} + } + Function {~MasterChannelControl()} {open + } { + code {free (data->sample); +delete data;} {} + } + Function {fadervalue(const double p_val)} {open + } { + code {double lin; +if (p_val == 0) { + lin=0; +} else { + lin=pow(10,(p_val-90)/60); +} +data->fadermult[0]=lin; +data->fadermult[1]=lin; +data->fadervalue=p_val; +data->parentui->redraw(); +//faderarray[channel]=lin; +//mixmute[channel]->draw(); +//mixfader[channel]->draw(); +//mixled[channel]->draw(); +//masterled[0]->draw(); +//masterled[1]->draw(); +//this->redraw();*/} {} + } + Function {fadervalue()} {open return_type double + } { + code {return data->fadervalue;} {} + } + Function {updatemeters()} {open return_type void + } { + code {// update and redraw meterlevels object +this->parentui()->mixledleft->control->setvalue(data->trackpeak[0]); +this->parentui()->mixledright->control->setvalue(data->trackpeak[1]); + +this->parentui()->mixledleft->redraw(); +this->parentui()->mixledright->redraw(); +// then, reset peak value +trackpeak(0,0); +trackpeak(1,0);} {} + } + Function {trackpeak(int lr)} {open return_type double + } { + code {return data->trackpeak[lr];} {} + } + Function {trackpeak(int lr,double peakval)} {open return_type void + } { + code {data->trackpeak[lr]=peakval;} {} + } + Function {parentui(MasterChannelUI* p_parentui)} {open return_type void + } { + code {data->parentui=p_parentui;} {} + } + Function {parentui()} {open return_type {MasterChannelUI*} + } { + code {return data->parentui;} {} + } + Function {sample(int framenum,float samval)} {open + } { + code {data->sample[framenum]=samval; +/*float q=1; +if (samval<0) { + q=-1; +} +if ((samval*q) > data->trackpeak) { + data->trackpeak=samval*q; +}*/} {} + } + Function {sample(int framenum)} {open return_type float + } { + code {return data->sample[framenum];} {} + } + Function {getfadermult(int lr)} {open return_type double + } { + code {return data->fadermult[lr];} {} + } + Function {mixmono(int inval)} {open return_type void + } { + code {data->mixmono=inval; +parentui()->mix_mono->value(inval); +parentui()->mix_mono->redraw();} {} + } + Function {mixmono()} {open return_type int + } { + code {return data->mixmono;} {} + } +} + +class MasterChannelUI {open : {public Fl_Group} +} { + decl {MasterChannelControl* control;} {public + } + Function {MasterChannelUI(int a,int b,int c,int d,const char* e):Fl_Group(a,b,c,d,e)} {open + } { + code {init_ui();} {} + } + Function {MasterChannelUI(int a,int b,int c,int d):Fl_Group(a,b,c,d,NULL)} {open + } { + code {init_ui();} {} + } + Function {init_ui()} {open private + } { + code {this->control=new MasterChannelControl(); +this->control->parentui(this); +make_window();} {} + } + Function {make_window()} {open + } { + Fl_Window channelstrip {open + xywh {889 373 30 235} type Double + code0 {o->position(this->x(),this->y());} + class Fl_Group visible + } { + Fl_Group mixledleft {open + xywh {2 92 4 132} + class MixerLevelMeterUI + } {} + Fl_Group mixledright {open + xywh {24 92 4 132} + class MixerLevelMeterUI + } {} + Fl_Slider fader { + callback {control->fadervalue(o->value());} + 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 + code0 {o->clear_visible_focus();} + } + Fl_Button mix_mono { + label MONO + callback {control->mixmono(o->value());} + xywh {0 68 30 15} type Toggle selection_color 3 labelsize 8 + code0 {o->clear_visible_focus();} + } + } + } + Function {~MasterChannelUI()} {open + } { + code {delete control;} {} + } +} + +class MixerData {open +} { + decl {MixerUI* parentui;} {} + decl {friend class MixerControl;} {} + decl {int eqon;} {} + decl {float* mixermasterout;} {public + } + decl {double trackpeak[2];} {public + } + decl {double fadermult[2];} {public + } + decl {__uint32 samplerate;} {public + } + decl {int selectedchannel;} {public + } + decl {double fadervalue;} {public + } + decl {__uint32 delaybuffersam;} {public + } + decl {int bypass;} {} +} + +class MixerControl {open +} { + decl {friend class MixerUI;} {} + decl {MixerData* data;} {} + Function {mix(int frames) /* <----------------------------------*/} {open + } { + code {int solo=0; +int trackon[24]; // 0=mute, 1=normal, 2=solo +MixerChannelControl* trackctl[24]; +for (int tracknum=0;tracknum<24;tracknum++) { + trackctl[tracknum]=parentui()->mixerchannel[tracknum]->control; + trackon[tracknum]=1; // normal + MixerChannelControl* track=trackctl[tracknum]; + if (track->issolo()!=0) { + solo=1; + trackon[tracknum]++; + } + if (track->ismute()!=0) { + trackon[tracknum]--; + } + track->eq_enabled(data->eqon); + track->pan_enabled(1-(parentui()->fader_master->control->mixmono())); + track->bypass(data->bypass); +} + +stereosample sam; +for (int i=0;isolo)) continue; + MixerChannelControl* track=trackctl[j]; + + track->getsample(&sam,i); + + outleft+=sam.left; + outright+=sam.right; + } + outleft*=parentui()->fader_master->control->getfadermult(0); + outright*=parentui()->fader_master->control->getfadermult(1); + + /* clipping */ + if (outleft>1) { + outleft=1; } + else { + if (outleft<-1) outleft=-1; + } + if (outright>1) { + outright=1; + } else { + if (outright<-1) outright=-1; + } + + + if (fabs(outleft) > parentui()->fader_master->control->trackpeak(0)) { + parentui()->fader_master->control->trackpeak(0,fabs(outleft)); + } + if (fabs(outright) > parentui()->fader_master->control->trackpeak(1)) { + parentui()->fader_master->control->trackpeak(1,fabs(outright)); + } + + /* / tape saturation emulation + if (parentui()->tapesaton->value()==1) + { + int tapewidth=100; + float myleft=0; + float myright=0; + for (int tapepos=0;tapeposmaxleft) { + myleft+=maxleft; + } else { + myleft+=outleft; + } + if (outright>maxright) { + myright+=maxright; + } else { + myright+=outright; + } + } + outleft=myleft/tapewidth; + outright=myright/tapewidth; + } */ + data->mixermasterout[i*25+0]=outleft; + data->mixermasterout[i*25+1]=outright; +}} {} + } + Function {init()} {open return_type void + } { + code {data->eqon=1; +data->mixermasterout=(float *)malloc(512000*sizeof(float)); +data->parentui=NULL; +data->selectedchannel=0; +data->bypass=1; + +return;} {} + } + Function {MixerControl()} {} { + code {data=new MixerData(); +data->parentui=NULL; +data->samplerate=0; +init();} {} + } + Function {~MixerControl()} {} { + code {free (data->mixermasterout); + +//delaybuffersize=maxreverbunits*maxreverbseconds*MAXSAMRATE; +//delaybuffer=(float *)malloc(sizeof(float)*delaybuffersize); +//if (delaybuffer==NULL) cout << " out of mem L" << endl; +//delaybuffersam=delaybuffersize; +//for (int i=0;iparentui=p_parentui;} {} + } + Function {parentui()} {return_type {MixerUI*} + } { + code {return data->parentui;} {} + } + Function {fadervalue(const double p_val)} {} { + code {double lin; +if (p_val == 0) { + lin=0; +} else { + lin=pow(10,(p_val-90)/60); +} +data->fadermult[0]=lin; +data->fadermult[1]=lin; +data->fadervalue=p_val; +//faderarray[channel]=lin; +//mixmute[channel]->draw(); +//mixfader[channel]->draw(); +//mixled[channel]->draw(); +//masterled[0]->draw(); +//masterled[1]->draw(); +parentui()->fader_master->fader->value(p_val); +parentui()->fader_master->redraw(); //this->redraw();*/} {} + } + Function {fadervalue()} {return_type double + } { + code {return data->fadervalue;} {} + } + Function {trackpeak(int lr)} {return_type double + } { + code {return data->trackpeak[lr];} {} + } + Function {trackpeak(int lr,double peakval)} {return_type void + } { + code {data->trackpeak[lr]=peakval;} {} + } + Function {masterout(int tracknum,int framenum)} {return_type float + } { + code {return data->mixermasterout[framenum*25+tracknum];} {} + } + Function {lin2dB(double lin)} {return_type double + } { + code {return log10(lin)*20.0;} {} + } + Function {dB2lin(double dB)} {return_type double + } { + code {return pow(10.0,dB/20.0);} {} + } + Function {selectedchannel(int channel_base0)} {return_type void + } { + code {data->selectedchannel=channel_base0; +for (int i=0;i<24;i++) { + if (channel_base0!=i) { + this->parentui()->mixerchannel[i]->control->channelselect(0); + } else { + this->parentui()->mixerchannel[i]->control->channelselect(1); + } +} +MixerChannelControl* mixcontrol=this->parentui()->mixerchannel[channel_base0]->control; + +// reloading controls with their own value causes a redraw. +mixcontrol->eq_gain(0,mixcontrol->eq_gain(0)); +mixcontrol->eq_gain(1,mixcontrol->eq_gain(1)); +mixcontrol->eq_gain(2,mixcontrol->eq_gain(2)); +mixcontrol->eq_gain(3,mixcontrol->eq_gain(3)); + +mixcontrol->eq_freq(0,mixcontrol->eq_freq(0)); +mixcontrol->eq_freq(1,mixcontrol->eq_freq(1)); +mixcontrol->eq_freq(2,mixcontrol->eq_freq(2)); +mixcontrol->eq_freq(3,mixcontrol->eq_freq(3)); + +mixcontrol->eq_on(0,mixcontrol->eq_on(0)); +mixcontrol->eq_on(1,mixcontrol->eq_on(1)); +mixcontrol->eq_on(2,mixcontrol->eq_on(2)); +mixcontrol->eq_on(3,mixcontrol->eq_on(3));} {} + } + Function {selectedchannel()} {return_type int + } { + code {return data->selectedchannel;} {} + } + Function {savemix(string* strfile)} {return_type {string*} + } { + code {fstream to_out(strfile->c_str(),ios::out); +if (to_out==NULL) { + string *error=new string(""); + *error+="Cannot open mix file for writing."; + return error; +} + +for (int i=0;i<24;i++) { + MixerChannelControl* track=parentui()->mixerchannel[i]->control; + to_out << "[Track="<mixerchannel[i]->control; + to_out << "[Track="<selectedchannel(ch-1); + continue; + } + MixerChannelControl* track=parentui()->mixerchannel[selectedchannel()]->control; + if (line.substr(0,8)=="[Master]") { + master=true; + continue; + } + if (master) { + if (line.substr(0,5)=="mono=") { + parentui()->fader_master->control->mixmono(Convert::str2long(line.substr(5,1))); + continue; + } + if (line.substr(0,5)=="eqon=") { + this->eq_on(Convert::str2long(line.substr(5,1))); + continue; + } + } + if (line.substr(0,5)=="solo=") { +// mixsolo[this->selectedchannel]->value(Convert::str2long(line.substr(5,1))); + track->solo(Convert::str2long(line.substr(5,1))); + continue; + } + if (line.substr(0,5)=="mute=") { +// mixmute[this->selectedchannel]->value(Convert::str2long(line.substr(5,1))); + track->mute(Convert::str2long(line.substr(5,1))); + continue; + } + if (line.substr(0,4)=="pan=") { + track->panvalue(Convert::str2dbl(line.substr(4,10))); + continue; + } + if ((line.substr(0,8)=="eq_freq[") + &&(line.substr(9,2)=="]=")) + { + int whicheq=Convert::str2long(line.substr(8,1)); + double freq=Convert::str2dbl(line.substr(11,10)); + track->eq_freq(whicheq,freq); + continue; + + } + if ((line.substr(0,8)=="eq_gain[") + &&(line.substr(9,2)=="]=")) + { + int whicheq=Convert::str2long(line.substr(8,1)); + double gain=Convert::str2dbl(line.substr(11,10)); + track->eq_gain(whicheq,gain); + continue; + + } + if ((line.substr(0,5)=="eq_Q[") + &&(line.substr(6,2)=="]=")) + { + int whicheq=Convert::str2long(line.substr(5,1)); + double Q=Convert::str2dbl(line.substr(8,10)); + track->eq_Q(whicheq,Q); + continue; + } + if ((line.substr(0,6)=="eq_on[") + &&(line.substr(7,2)=="]=")) + { + int whicheq=Convert::str2long(line.substr(6,1)); + int onoff=Convert::str2long(line.substr(9,10)); + track->eq_on(whicheq,onoff); + continue; + } + if (line.substr(0,6)=="fader=") { + if (master) { + this->fadervalue(Convert::str2dbl(line.substr(6,10))); + } + else + { + track->fadervalue(Convert::str2dbl(line.substr(6,10))); + + } + + continue; + } + + cout << "Unknown setting, ignoring: " << line << endl; +} +this->selectedchannel(savechan); +from_in.close(); + +return NULL;} {} + } + Function {loadtrackmix(string* strfile,int base0track)} {open return_type {string*} + } { + code {fstream from_in(strfile->c_str(),ios::in); +if (from_in==NULL) { + string *error=new string(""); + *error+="Cannot open mix file for writing."; + return error; +} +string line; +int savechan=base0track; +while (!(from_in.eof())) +{ + getline(from_in,line); + if (line=="") continue; + if (line.substr(0,7)=="[Track=") { + continue; + } + MixerChannelControl* track=parentui()->mixerchannel[selectedchannel()]->control; + if (line.substr(0,5)=="solo=") { +// mixsolo[this->selectedchannel]->value(Convert::str2long(line.substr(5,1))); + track->solo(Convert::str2long(line.substr(5,1))); + continue; + } + if (line.substr(0,5)=="mute=") { +// mixmute[this->selectedchannel]->value(Convert::str2long(line.substr(5,1))); + track->mute(Convert::str2long(line.substr(5,1))); + continue; + } + if (line.substr(0,4)=="pan=") { + track->panvalue(Convert::str2dbl(line.substr(4,10))); + continue; + } + if ((line.substr(0,8)=="eq_freq[") + &&(line.substr(9,2)=="]=")) + { + int whicheq=Convert::str2long(line.substr(8,1)); + double freq=Convert::str2dbl(line.substr(11,10)); + track->eq_freq(whicheq,freq); + continue; + + } + if ((line.substr(0,8)=="eq_gain[") + &&(line.substr(9,2)=="]=")) + { + int whicheq=Convert::str2long(line.substr(8,1)); + double gain=Convert::str2dbl(line.substr(11,10)); + track->eq_gain(whicheq,gain); + continue; + + } + if ((line.substr(0,5)=="eq_Q[") + &&(line.substr(6,2)=="]=")) + { + int whicheq=Convert::str2long(line.substr(5,1)); + double Q=Convert::str2dbl(line.substr(8,10)); + track->eq_Q(whicheq,Q); + continue; + } + if ((line.substr(0,6)=="eq_on[") + &&(line.substr(7,2)=="]=")) + { + int whicheq=Convert::str2long(line.substr(6,1)); + int onoff=Convert::str2long(line.substr(9,10)); + track->eq_on(whicheq,onoff); + continue; + } + if (line.substr(0,6)=="fader=") { + track->fadervalue(Convert::str2dbl(line.substr(6,10))); + continue; + } + + cout << "Unknown setting, ignoring: " << line << endl; +} +this->selectedchannel(savechan); +from_in.close(); + +return NULL;} {} + } + Function {updatemeters()} {open + } { + code {MixerUI* pui=this->parentui(); +if (pui==NULL) return; +for (int tracknum=0;tracknum<24;tracknum++) { + pui->mixerchannel[tracknum]->control->updatemeters(); +} +// update and redraw meterlevels object +pui->fader_master->control->updatemeters();} {} + } + Function {samplerate(__uint32 p_samplerate)} {open return_type void + } { + code {data->samplerate=p_samplerate; + +MixerUI* pui=this->parentui(); +if (pui==NULL) return; +for (int tracknum=0;tracknum<24;tracknum++) { + pui->mixerchannel[tracknum]->control->samplerate(p_samplerate); +}} {} + } + Function {samplerate()} {open return_type __uint32 + } { + code {return data->samplerate;} {} + } + Function {eq_on(int onoff)} {return_type void + } { + code {data->eqon=onoff; +parentui()->eqon->value(onoff); +parentui()->eqon->redraw();} {} + } + Function {eq_on()} {open return_type int + } { + code {return data->eqon;} {} + } + Function {bypass()} {return_type int + } { + code {return data->bypass;} {} + } + Function {bypass(int onoff)} {return_type void + } { + code {data->bypass=onoff; +parentui()->bypass->value(onoff); +parentui()->bypass->redraw();} {} + } +} + +class MixerUI {open : {public Fl_Group} +} { + decl {MixerControl* control;} {public + } + decl {MixerChannelUI* mixerchannel[24];} {public + } + decl {/* ===MIXER UI stuff ===================================================== */} {} + decl {HD24UserInterface* ui;} {} + decl {Fl_Window* window} {} + Function {make_window() /*<-----------------------------------*/} {open + } { + Fl_Window mixgroup {open + xywh {41 257 605 460} type Double + code0 {o->position(this->x(),this->y());} + class Fl_Group visible + } { + Fl_Group resources {open + xywh {70 52 150 98} hide deactivate + } { + Fl_Button button_small_up { + tooltip arm image {images/button_small.gif} xywh {75 52 145 13} deactivate + } + Fl_Button button_small_dn { + tooltip arm image {images/button_small_dn.gif} xywh {70 52 5 13} deactivate + } + } + Fl_Group mixergroup {open + xywh {-9 0 643 463} + code0 {init_gui();} + } { + Fl_Box {} { + xywh {-9 354 625 109} box BORDER_BOX + } + Fl_Box {} { + label S + tooltip Solo xywh {5 269 10 14} color 1 selection_color 1 labelfont 1 labelsize 12 + } + Fl_Box {} { + label M + tooltip Mute xywh {5 286 10 14} color 1 selection_color 1 labelfont 1 labelsize 12 + } + Fl_Group channelgroup {open selected + xywh {0 210 584 250} deactivate + } { + Fl_Group mixerchannel1 {open + xywh {17 221 20 231} box BORDER_BOX color 7 + code0 {mixerchannel[0]=o;} + class MixerChannelUI + } {} + Fl_Group mixerchannel2 {open + xywh {37 221 20 231} box BORDER_BOX color 7 + code0 {mixerchannel[1]=o;} + class MixerChannelUI + } {} + Fl_Group mixerchannel3 {open + xywh {57 221 20 231} box BORDER_BOX color 7 + code0 {mixerchannel[2]=o;} + class MixerChannelUI + } {} + Fl_Group mixerchannel4 {open + xywh {77 221 20 231} box BORDER_BOX color 7 + code0 {mixerchannel[3]=o;} + class MixerChannelUI + } {} + Fl_Group mixerchannel5 {open + xywh {97 221 20 231} box BORDER_BOX color 7 + code0 {mixerchannel[4]=o;} + class MixerChannelUI + } {} + Fl_Group mixerchannel6 {open + xywh {117 221 20 231} box BORDER_BOX color 7 + code0 {mixerchannel[5]=o;} + class MixerChannelUI + } {} + Fl_Group mixerchannel7 {open + xywh {137 221 20 231} box BORDER_BOX color 7 + code0 {mixerchannel[6]=o;} + class MixerChannelUI + } {} + Fl_Group mixerchannel8 {open + xywh {157 221 20 231} box BORDER_BOX color 7 + code0 {mixerchannel[7]=o;} + class MixerChannelUI + } {} + Fl_Group mixerchannel9 {open + xywh {177 221 20 231} box BORDER_BOX color 7 + code0 {mixerchannel[8]=o;} + class MixerChannelUI + } {} + Fl_Group mixerchannel10 {open + xywh {197 221 20 231} box BORDER_BOX color 7 + code0 {mixerchannel[9]=o;} + class MixerChannelUI + } {} + Fl_Group mixerchannel11 {open + xywh {217 221 20 231} box BORDER_BOX color 7 + code0 {mixerchannel[10]=o;} + class MixerChannelUI + } {} + Fl_Group mixerchannel12 {open + xywh {237 221 20 231} box BORDER_BOX color 7 + code0 {mixerchannel[11]=o;} + class MixerChannelUI + } {} + Fl_Group mixerchannel13 {open + xywh {257 221 20 231} box BORDER_BOX color 7 + code0 {mixerchannel[12]=o;} + class MixerChannelUI + } {} + Fl_Group mixerchannel14 {open + xywh {277 221 20 231} box BORDER_BOX color 7 + code0 {mixerchannel[13]=o;} + class MixerChannelUI + } {} + Fl_Group mixerchannel15 {open + xywh {297 221 20 231} box BORDER_BOX color 7 + code0 {mixerchannel[14]=o;} + class MixerChannelUI + } {} + Fl_Group mixerchannel16 {open + xywh {317 221 20 231} box BORDER_BOX color 7 + code0 {mixerchannel[15]=o;} + class MixerChannelUI + } {} + Fl_Group mixerchannel17 {open + xywh {337 221 20 231} box BORDER_BOX color 7 + code0 {mixerchannel[16]=o;} + class MixerChannelUI + } {} + Fl_Group mixerchannel18 {open + xywh {357 221 20 231} box BORDER_BOX color 7 + code0 {mixerchannel[17]=o;} + class MixerChannelUI + } {} + Fl_Group mixerchannel19 {open + xywh {377 221 20 231} box BORDER_BOX color 7 + code0 {mixerchannel[18]=o;} + class MixerChannelUI + } {} + Fl_Group mixerchannel20 {open + xywh {397 221 20 231} box BORDER_BOX color 7 + code0 {mixerchannel[19]=o;} + class MixerChannelUI + } {} + Fl_Group mixerchannel21 {open + xywh {417 221 20 231} box BORDER_BOX color 7 + code0 {mixerchannel[20]=o;} + class MixerChannelUI + } {} + Fl_Group mixerchannel22 {open + xywh {437 221 20 231} box BORDER_BOX color 7 + code0 {mixerchannel[21]=o;} + class MixerChannelUI + } {} + Fl_Group mixerchannel23 {open + xywh {457 221 20 231} box BORDER_BOX color 7 + code0 {mixerchannel[22]=o;} + class MixerChannelUI + } {} + Fl_Group mixerchannel24 {open + xywh {477 221 20 231} box BORDER_BOX color 7 + code0 {mixerchannel[23]=o;} + class MixerChannelUI + } {} + } + Fl_Tabs {} {open + xywh {10 25 435 195} + } { + Fl_Group eqgroup { + label EQ open + xywh {10 45 435 175} labelfont 1 labelsize 10 deactivate + } { + Fl_Dial gain1 { + callback {mixerchannel[control->selectedchannel()]->control->eq_gain(0,o->value());} + xywh {20 159 30 30} minimum -20 maximum 20 step 10 + class WidgetPDial + } + Fl_Dial gain2 { + callback {mixerchannel[control->selectedchannel()]->control->eq_gain(1,o->value());} + xywh {65 159 30 30} minimum -20 maximum 20 step 10 + class WidgetPDial + } + Fl_Dial gain3 { + callback {mixerchannel[control->selectedchannel()]->control->eq_gain(2,o->value());} + xywh {110 159 30 30} minimum -20 maximum 20 step 10 + class WidgetPDial + } + Fl_Dial gain4 { + label GAIN + callback {mixerchannel[control->selectedchannel()]->control->eq_gain(3,o->value());} + xywh {155 159 30 30} labelfont 1 labelsize 12 align 8 minimum -20 maximum 20 step 10 + class WidgetPDial + } + Fl_Dial freq1 { + callback {mixerchannel[control->selectedchannel()]->control->eq_freq(0,o->value());} + xywh {20 125 30 30} minimum 20 maximum 200 step 10 value 100 + class WidgetPDial + } + Fl_Dial freq2 { + callback {mixerchannel[control->selectedchannel()]->control->eq_freq(1,o->value());} + xywh {65 125 30 30} minimum 150 maximum 1000 step 20 value 600 + class WidgetPDial + } + Fl_Dial freq3 { + callback {mixerchannel[control->selectedchannel()]->control->eq_freq(2,o->value());} + xywh {110 125 30 30} minimum 800 maximum 3000 step 10 value 1600 + class WidgetPDial + } + Fl_Dial freq4 { + label FREQ + callback {mixerchannel[control->selectedchannel()]->control->eq_freq(3,o->value());} + xywh {155 125 30 30} labelfont 1 labelsize 12 align 8 minimum 3000 maximum 12000 step 1 value 6000 + class WidgetPDial + } + Fl_Check_Button eqon1 { + label { Low} + callback {mixerchannel[control->selectedchannel()]->control->eq_on(0,o->value());} + xywh {15 95 20 15} down_box DOWN_BOX value 1 labelsize 12 align 5 + } + Fl_Check_Button eqon2 { + label {Lo/Mid} + callback {mixerchannel[control->selectedchannel()]->control->eq_on(1,o->value());} + xywh {60 95 20 15} down_box DOWN_BOX value 1 labelsize 12 align 5 + } + Fl_Check_Button eqon3 { + label {Hi/Mid} + callback {mixerchannel[control->selectedchannel()]->control->eq_on(2,o->value());} + xywh {105 95 20 15} down_box DOWN_BOX value 1 labelsize 12 align 5 + } + Fl_Check_Button eqon4 { + label High + callback {mixerchannel[control->selectedchannel()]->control->eq_on(3,o->value());} + xywh {150 95 20 15} down_box DOWN_BOX value 1 labelsize 12 align 5 + } + Fl_Check_Button eqon { + label {Enable equalizer (all channels)} + callback {control->eq_on(o->value());} + xywh {15 50 205 20} down_box DOWN_BOX value 1 labelsize 12 + } + Fl_Check_Button reverbon { + label {Reverb (not yet available)} + callback {//mixerchannel[control->selectedchannel()]->control->reverb_on(o->value());} + xywh {240 95 175 15} down_box DOWN_BOX value 1 labelsize 12 deactivate + } + Fl_Check_Button tapesaton { + label {Tape emulation} + callback {//mixerchannel[control->selectedchannel()]->control->reverb_on(o->value());} + xywh {240 80 175 15} down_box DOWN_BOX value 1 labelsize 12 deactivate + } + Fl_Output dispgain1 { + xywh {15 190 40 15} box FLAT_BOX color 53 labelsize 10 align 0 textsize 10 + } + Fl_Output dispgain2 { + xywh {60 190 40 15} box FLAT_BOX color 53 labelsize 10 align 0 textsize 10 + } + Fl_Output dispgain3 { + xywh {105 190 40 15} box FLAT_BOX color 53 labelsize 10 align 0 textsize 10 + } + Fl_Output dispgain4 { + xywh {150 190 40 15} box FLAT_BOX color 53 labelsize 10 align 0 textsize 10 + } + Fl_Output dispfreq1 { + xywh {15 109 40 15} box FLAT_BOX color 53 labelsize 10 align 0 textsize 10 + } + Fl_Output dispfreq2 { + xywh {60 109 40 15} box FLAT_BOX color 53 labelsize 10 align 0 textsize 10 + } + Fl_Output dispfreq3 { + xywh {105 109 40 15} box FLAT_BOX color 53 labelsize 10 align 0 textsize 10 + } + Fl_Output dispfreq4 { + xywh {150 109 40 15} box FLAT_BOX color 53 labelsize 10 align 0 textsize 10 + } + } + Fl_Tabs {} { + label AUX + xywh {10 45 330 175} labelfont 1 labelsize 10 hide + } {} + } + Fl_Button bypass { + label {Bypass Mixer} + callback {control->bypass(o->value()); + +switch (o->value()) +{ + case 0: + eqgroup->activate(); + channelgroup->activate(); + break; + case 1: + eqgroup->deactivate(); + channelgroup->deactivate(); + break; + +}} + tooltip Solo xywh {10 0 90 20} type Toggle value 1 selection_color 1 labelsize 12 + } + Fl_Group fader_master {open + xywh {574 221 20 231} box BORDER_BOX color 7 + class MasterChannelUI + } {} + } + } + } + Function {MixerUI(int a,int b,int c,int d):Fl_Group(a,b,c,d,NULL)} {open + } { + code {control=new MixerControl(); +control->parentui(this); +this->window=(Fl_Window*)(this->make_window());} {} + } + Function {~MixerUI()} {open + } { + code {delete control;} {} + } + Function {init_gui()} {open + } { + code {int starty=(mixerchannel[0]->y()); +int startx=(mixerchannel[0]->x()); +fader_master->clear_visible_focus(); +for (int i=1;i<=24;i++) +{ + if (i==1) { + mixerchannel[i-1]->control->channelselect(1); + } + mixerchannel[i-1]->position(startx+((i-1)*23),starty); +// mixerchannel[i-1]->size(mixerchannel[0]->w(),mixerchannel[0]->h()); + mixerchannel[i-1]->clear_visible_focus(); + mixerchannel[i-1]->control->channel_number(i); + + mixerchannel[i-1]->control->parentmixercontrol(this->control); + + // set values on freq/gain displays: + mixerchannel[i-1]->control->eq_freq(0,mixerchannel[i-1]->control->eq_freq(0)); + mixerchannel[i-1]->control->eq_freq(1,mixerchannel[i-1]->control->eq_freq(1)); + mixerchannel[i-1]->control->eq_freq(2,mixerchannel[i-1]->control->eq_freq(2)); + mixerchannel[i-1]->control->eq_freq(3,mixerchannel[i-1]->control->eq_freq(3)); + + mixerchannel[i-1]->control->eq_gain(0,mixerchannel[i-1]->control->eq_gain(0)); + mixerchannel[i-1]->control->eq_gain(1,mixerchannel[i-1]->control->eq_gain(1)); + mixerchannel[i-1]->control->eq_gain(2,mixerchannel[i-1]->control->eq_gain(2)); + mixerchannel[i-1]->control->eq_gain(3,mixerchannel[i-1]->control->eq_gain(3)); + + +// eq_freq[(i-1)*eqperchan+0]=100; +// eq_freq[(i-1)*eqperchan+1]=600; +// eq_freq[(i-1)*eqperchan+2]=1600; +// eq_freq[(i-1)*eqperchan+3]=6000; +// eq_on[(i-1)*eqperchan+0]=eqon1->value(); +// eq_on[(i-1)*eqperchan+1]=eqon2->value(); +// eq_on[(i-1)*eqperchan+2]=eqon3->value(); +// eq_on[(i-1)*eqperchan+3]=eqon4->value(); +// for (int j=0;j<4;j++) { +// eq_gain[(i-1)*eqperchan+j]=0; +// +// eq_Q[(i-1)*eqperchan+j]=1; +// eq_type[(i-1)*eqperchan+j]=7; +// } + mixerchannel[i-1]->clear_visible_focus(); +// mixsolo[i-1]->position(8+(startx)+((i-1)*23),mixsolo[i-1]->y()); +// mixsolo[i-1]->size(mixsolo[0]->w(),mixsolo[0]->h()); +// mixsolo[i-1]->up_image(mixsolo[0]->up_image()); +// mixsolo[i-1]->down_image(mixsolo[0]->down_image()); + +// mixmute[i-1]->position(mixsolo[i-1]->x(),mixmute[i-1]->y()); +// mixmute[i-1]->size(mixmute[0]->w(),mixmute[0]->h()); +// mixmute[i-1]->up_image(mixmute[0]->up_image()); +// mixmute[i-1]->down_image(mixmute[0]->down_image()); + +// mixfader[i-1]->position(mixsolo[i-1]->x(),mixfader[i-1]->y()); +// mixfader[i-1]->size(mixfader[0]->w(),mixfader[0]->h()); + +// mixchsel[i-1]->position(mixsolo[i-1]->x(),mixchsel[i-1]->y()); +// mixpan[i-1]->position(mixsolo[i-1]->x(),mixpan[i-1]->y()); +// mixled[i-1]->position(mixfader[i-1]->x()+17,mixfader[0]->y()); + mixerchannel[i-1]->control->fadervalue(90); +} + +//masterled[0]->position(fader_master->x()-2,fader_master->y()); +//masterled[1]->position(fader_master->x()+17,fader_master->y()); +fader_master->control->fadervalue(90); +//this->selectedchannel(0);} {} + } + Function {set_ui(HD24UserInterface* p_ui)} {open return_type void + } { + code {this->ui=p_ui;} {} + } + Function {loadfromfile()} {open return_type void + } { + code {string* mixdir=hd24utils::getlastdir("mixdir"); + +Fl_Native_File_Chooser chooser; +chooser.directory(mixdir->c_str()); +delete mixdir; + +chooser.title("Select a mix to load\\0"); +chooser.type(Fl_Native_File_Chooser::BROWSE_FILE); +chooser.filter("Mixer settings\\t*.{mix}\\0"); +//chooser.preview(0); +switch (chooser.show()) { + case -1: break; //error + case 1: break; //cancel + default: + if (chooser.filename()) { + string* cfilename=new string(chooser.filename()); + + //cout << "filename = " << *strfile << endl; + string* fpath=new string(""); + *fpath+=cfilename->substr(0,strlen(cfilename->c_str())-strlen(fl_filename_name(cfilename->c_str()))); + hd24utils::setlastdir("mixdir",fpath->c_str()); + control->loadmix(cfilename); + delete fpath; + delete cfilename; + } + break; +}} {} + } + Function {savetofile()} {open return_type void + } { + code {string* mixdir=new string(""); +*mixdir+=*(hd24utils::getlastdir("mixdir")); + +Fl_Native_File_Chooser chooser; +chooser.filter("Mix files\\t*.mix"); +chooser.title("Save mixer settings to file"); +chooser.directory(mixdir->c_str()); +chooser.options(Fl_Native_File_Chooser::NEW_FOLDER); +chooser.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); + +switch (chooser.show()) { + case -1: break; //error + case 1: break; //cancel + default: + // save header to chooser.filename() + + bool bFileexists=false; + if (bFileexists) { + bool choice=ui->confirm( + "A file with this name already exists. Do you wish to overwrite it?" + ); + if (!(choice)) return; + } + string* strfile=new string(chooser.filename()); + //cout << "filename = " << *strfile << endl; + string* fpath=new string(""); + *fpath+=strfile->substr(0,strlen(strfile->c_str())-strlen(fl_filename_name(strfile->c_str()))); + hd24utils::setlastdir("mixdir",fpath->c_str()); + + string* anyerrors=control->savemix(strfile); + + delete strfile; + delete fpath; + if (anyerrors==NULL) { + fl_message("Mix file saved successfully."); + } else { + delete anyerrors; + fl_message("Could not write mix file. Access denied? Disk full?"); + } + break; +} +delete mixdir;} {} + } + Function {loadtrackmixfromfile()} {open return_type void + } { + code {string* mixdir=hd24utils::getlastdir("mixdir"); + +Fl_Native_File_Chooser chooser; +chooser.directory(mixdir->c_str()); +delete mixdir; + +chooser.title("Select a mix to load\\0"); +chooser.type(Fl_Native_File_Chooser::BROWSE_FILE); +chooser.filter("Mixer settings\\t*.{mix}\\0"); +//chooser.preview(0); +switch (chooser.show()) { + case -1: break; //error + case 1: break; //cancel + default: + if (chooser.filename()) { + string* cfilename=new string(chooser.filename()); + + //cout << "filename = " << *strfile << endl; + string* fpath=new string(""); + *fpath+=cfilename->substr(0,strlen(cfilename->c_str())-strlen(fl_filename_name(cfilename->c_str()))); + hd24utils::setlastdir("mixdir",fpath->c_str()); + control->loadtrackmix(cfilename,control->selectedchannel()); + delete fpath; + delete cfilename; + } + break; +}} {} + } + Function {savetrackmixtofile()} {open return_type void + } { + code {string* mixdir=new string(""); +*mixdir+=*(hd24utils::getlastdir("mixdir")); + +Fl_Native_File_Chooser chooser; +chooser.filter("Mix files\\t*.mix"); +chooser.title("Save mixer settings to file"); +chooser.directory(mixdir->c_str()); +chooser.options(Fl_Native_File_Chooser::NEW_FOLDER); +chooser.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE); + +switch (chooser.show()) { + case -1: break; //error + case 1: break; //cancel + default: + // save header to chooser.filename() + + bool bFileexists=false; + if (bFileexists) { + bool choice=ui->confirm( + "A file with this name already exists. Do you wish to overwrite it?" + ); + if (!(choice)) return; + } + string* strfile=new string(chooser.filename()); + //cout << "filename = " << *strfile << endl; + string* fpath=new string(""); + *fpath+=strfile->substr(0,strlen(strfile->c_str())-strlen(fl_filename_name(strfile->c_str()))); + hd24utils::setlastdir("mixdir",fpath->c_str()); + + string* anyerrors=control->savetrackmix(strfile,control->selectedchannel()); + + delete strfile; + if (anyerrors==NULL) { + fl_message("Mix file saved successfully."); + } else { + delete anyerrors; + fl_message("Could not write mix file. Access denied? Disk full?"); + } + delete fpath; + break; +} +delete mixdir;} {} + } +} 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 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0109 +header_name {.h} +code_name {.cxx} +decl {\#define RECORDERDEBUG 0} {public +} + +decl {\#define MAXSAMRATE 48000} {public +} + +decl {\#define AUDIOLIB_PORTAUDIO 1} {public +} + +decl {\#define AUDIOLIB_JACK 2} {public +} + +decl {\#define AUDIOLIB_SNDFILE 3} {public +} + +decl {\#define Pi2 (2*3.1415926535897)} {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {class MixerControl;} {public +} + +decl {\#include } {public +} + +decl {class RecorderChannelData;} {public +} + +decl {class RecorderChannelControl;} {public +} + +decl {class RecorderChannelUI;} {public +} + +decl {class RecorderData;} {public +} + +decl {class RecorderControl;} {public +} + +decl {class RecorderUI;} {public +} + +class ScrubWheel {: {public Fl_Roller} +} { + decl {int myval;} {} + decl {RecorderUI* ui;} {} + decl {int lastx;} {} + Function {handle(int e)} {open return_type int + } { + code {/*char *fltk_eventnames[] = +{ + "FL_NO_EVENT", + "FL_PUSH", + "FL_RELEASE", + "FL_ENTER", + "FL_LEAVE", + "FL_DRAG", + "FL_FOCUS", + "FL_UNFOCUS", + "FL_KEYDOWN", + "FL_KEYUP", + "FL_CLOSE", + "FL_MOVE", + "FL_SHORTCUT", + "FL_DEACTIVATE", + "FL_ACTIVATE", + "FL_HIDE", + "FL_SHOW", + "FL_PASTE", + "FL_SELECTIONCLEAR", + "FL_MOUSEWHEEL", + "FL_DND_ENTER", + "FL_DND_DRAG", + "FL_DND_LEAVE", + "FL_DND_RELEASE", +}; + +*/ +if (e==FL_DRAG) { + myval=Fl::event_x()-lastx; + RecorderControl::button_scrub_call(myval,this->ui->control); +} +lastx=Fl::event_x(); +return 1;} {} + } + Function {ScrubWheel(int a,int b,int c,int d,const char* e):Fl_Roller(a,b,c,d,e)} {open + } { + code {myval=0;} {} + } + Function {draw()} {open + } { + code {//draw goes here +return Fl_Roller::draw();} {} + } + Function {value()} {open return_type int + } { + code {return this->myval;} {} + } + Function {value(int newval)} {open return_type int + } { + code {int oldval=this->myval; +this->myval=newval; // not very useful but whatever +return oldval;} {} + } + Function {setui(RecorderUI* p_ui)} {open + } { + code {this->ui=p_ui;} {} + } +} + +class AudioSystem {open +} { + decl {AudioStorage* tape;} {} + decl {__uint32 samrate;} {public + } + decl {bool closingdown;} {public + } + decl {MixerControl* mixercontrol;} {} + decl {RecorderControl* recorder;} {} + decl {PortAudioWrapper* portaudio;} {public + } + decl {SoundFileWrapper* soundfile;} {public + } + decl {JackWrapper* libjack;} {} + decl {PaStreamParameters* inputParameters;} {} + decl {PaStreamParameters* outputParameters;} {} + decl {PaStream* portaudiostream;} {} + decl {jack_client_t *jackclient;} {} + decl {__uint32 jackrate;} {} + decl {__uint32 portaudiooffset;} {public + } + decl {int as_initialized;} {} + decl {int portaudio_initialized;} {} + decl {int jack_initialized;} {} + decl {int as_looppos;} {} + decl {bool as_mustloop;} {} + decl {jack_port_t *output_port[24];} {} + decl {jack_port_t *output_master[2];} {} + decl {jack_port_t *input_port[24];} {} + decl {long* mtsample;} {} + decl {bool havestreamtime;} {} + decl {__sint64 streamtime;} {public + } + Function {AudioSystem(RecorderControl* rec)} {open + } { + code {\#if (RECORDERDEBUG==1) +cout << "AudioSystem::AudioSystem()" << endl; +\#endif +initvars(rec);} {} + } + Function {initvars(RecorderControl* rec)} {open return_type void + } { + code {this->tape=NULL; +this->samrate=0; +this->closingdown=false; +this->mixercontrol=NULL; +this->recorder=rec; +this->portaudio=NULL; +this->soundfile=NULL; +this->libjack=NULL; +this->jackclient=NULL; +this->portaudiostream=NULL; +this->portaudio_initialized=0; +this->as_initialized=false; +this->jack_initialized=false; +this->as_looppos=0; +this->as_mustloop=false; +this->inputParameters=NULL; +this->outputParameters=NULL; +this->inputParameters=new PaStreamParameters; +this->outputParameters=new PaStreamParameters; +this->mtsample=NULL; +for (int i=0;i<24;i++) { + this->output_port[i]=NULL; + this->input_port[i]=NULL; +} +this->output_master[0]=NULL; +this->output_master[1]=NULL; +this->havestreamtime=false;} {} + } + Function {currentlocation(__uint32 newpos)} {open return_type void + } { + code {if (tape==NULL) return; +tape->currentlocation(newpos);} {} + } + Function {currentlocation()} {return_type __uint32 + } { + code {if (tape==NULL) return 0; +return tape->currentlocation();} {} + } + Function {jack_process(jack_nframes_t nframes, void *arg)} {open private return_type {static int} + } { + code {\#ifndef LIBJACK +\#if (RECORDERDEBUG==1) +cout << "no libjack" << endl; +\#endif +\#endif + +\#ifdef LIBJACK + +RecorderControl* recordercontrol=(RecorderControl*)arg; + +if (recordercontrol==NULL) { + cout << "no control" << endl; + return 0; +} +AudioSystem* audio=recordercontrol->audio; +if (audio==NULL) +{ + cout << "no audiosys" << endl; + return 0; +} +if ((audio->libjack)==NULL) +{ +\#if (RECORDERDEBUG==1) +cout << "no libjack" << endl; +\#endif + return 0; +} + +if (!(audio->libjack->libloaded)) +{ + cout << "no jacklib" << endl; + return 0; +} + +RecorderControl* mythis=recordercontrol; +//RecorderUI* mythis=recordercontrol; //(RecorderUI*)arg; +//AudioSystem* audio=mythis->control->audio; + + +jack_client_t* currjackclient=audio->jackclient; +if (currjackclient==NULL) return 0; +MixerControl* mixer=audio->mixer(); +if (mixer==NULL) return 0; +jack_position_t current; +jack_transport_state_t transport_state=audio->libjack->jack_transport_query(currjackclient,¤t); + +hd24song* mysong=(hd24song*)audio->tape; +if (mysong==NULL) return 0; /* nothing to do! */ + +hd24fs* myfs=mysong->fs(); + +__sint64 frame_time = (__sint64)(audio->libjack->jack_get_current_transport_frame(currjackclient)); + +MixerChannelControl* mixerchannel[24]; + + +for (unsigned int tracknum=0;tracknumparentui()->mixerchannel[tracknum]->control; +} + +unsigned int i; +__sint64 intsamval=0; +mysong->golocatepos(frame_time); +int jumpedloop=0; +if (transport_state!=JackTransportStopped) +{ + __sint64 frpos=frame_time; + __sint64 posoffset=0; + for (i=0;iloopmode()==1 ) + { + posoffset++; + if ((frpos+i)==(__sint64)(mysong->getlocatepos(hd24song::LOCATEPOS_LOOPEND))) + { + frpos=mysong->getlocatepos(hd24song::LOCATEPOS_LOOPSTART); + mysong->golocatepos(frpos); + posoffset=0; + jumpedloop=1; + } + } + + mysong->getmultitracksample( + (long*)((&audio->mtsample[i*25])), + hd24song::READMODE_REALTIME + ); + } + if (jumpedloop==1) + { + audio->hd24_transport_locate((__sint64)(frpos+posoffset)); + } +} + +for (unsigned int tracknum=0;tracknumlibjack->jack_port_get_buffer (audio->output_port[tracknum], nframes)); + jack_default_audio_sample_t *in = + (jack_default_audio_sample_t *)(audio->libjack->jack_port_get_buffer (audio->input_port[tracknum], nframes)); + for (i=0;imtsample[i*25+tracknum])); + intsamval=xb[0]; + intsamval=((intsamval>>16)+((intsamval%256)<<16)+(intsamval & 0xff00)); + if (intsamval>=(1<<23)) { + intsamval-=(1<<24); + } + double samval=(intsamval/(double)0x800000); + out[i]=samval; // send pre-fader, pre-mixer channel output to JACK + } else { + out[i]=0; + } + + mixerchannel[tracknum]->sample(i,out[i]); + + // ... except if we are monitoring input, in which case regular reading etc is + // still going on, but we will just copy the incoming signal to the output: + // (with the possible exception of tracks being recorded but that's for later) + if (myfs->isallinput()) { + out[i]=in[i]; + } + + if (fabs(out[i]) > mythis->data->trackpeak[i]) { + mythis->data->trackpeak[tracknum]=fabs(out[i]); + } + } +} +mixer->mix(nframes); +jack_default_audio_sample_t *masterL = +(jack_default_audio_sample_t *)(audio->libjack->jack_port_get_buffer (audio->output_master[0], nframes)); +jack_default_audio_sample_t *masterR = +(jack_default_audio_sample_t *)(audio->libjack->jack_port_get_buffer (audio->output_master[1], nframes)); +if ((masterL!=NULL)&&(masterR!=NULL)) { + for (i=0;imasterout(0,i); // left + masterR[i] = mixer->masterout(1,i); // right + } +} +\#endif + +return 0;} {} + } + Function {jack_shutdown(void *arg)} {private return_type {static void} + } { + code {\#ifdef LIBJACK +AudioSystem* audio=(AudioSystem*)arg; +if (audio->jackclient==NULL) { + return; +} +if (audio->mtsample!=NULL) { + memutils::myfree("jack_shutdown",audio->mtsample); + audio->mtsample=NULL; +} +audio->jackclient=NULL; +return; +\#endif} {} + } + Function {jackinit()} {open private return_type void + } { + code {if (portaudio_initialized==1) +{ +\#if (RECORDERDEBUG==1) + cout << "not initializing jack because portaudio is active" << endl; +\#endif + return; +} +if (!(libjack->libloaded)) +{ +\#if (RECORDERDEBUG==1) + cout << "not initializing jack because its lib is not loaded" << endl; +\#endif + return; +} +if (this->closingdown) { + if (jackclient!=NULL) + { + jack_shutdown(this); + } + jackclient=NULL; + return; +} +\#ifdef LIBJACK +//button_setlocate->value(0); +//highlight_setbuttons(0); // value of setlocate button +//mustdisplaytimer=true; +if (jackclient==NULL) { + jackclient = libjack->jack_client_new("HD24connect"); + + if (jackclient == NULL) { + // error: jack open failed. +\#if (RECORDERDEBUG==1) + cout << "error: jack open failed." << endl; +\#endif + return; + } + mtsample=(long *)memutils::mymalloc("jackinit",512000,1); + + libjack->jack_set_process_callback ( + jackclient, + (int (*)(jack_nframes_t, void*))jack_process, + recorder); // was: this (=audiosystem) + libjack->jack_on_shutdown (jackclient, jack_shutdown, this); + jackrate=libjack->jack_get_sample_rate (jackclient); + int i; + for (i=1;i<=MAXCHANNELS;i++) { + string portnameout="output"; + string portnamein="input"; + + string* tracknum=Convert::int2str(i); + portnameout+=*tracknum; + portnamein+=*tracknum; + delete(tracknum); + + output_port[i-1]=libjack->jack_port_register (jackclient, portnameout.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + input_port[i-1]=libjack->jack_port_register (jackclient, portnamein.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0); + } + string portnameout="master_out_L"; + output_master[0]=libjack->jack_port_register (jackclient, portnameout.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + portnameout="master_out_R"; + output_master[1]=libjack->jack_port_register (jackclient, portnameout.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0); + if (libjack->jack_activate(jackclient)) { +\#if (RECORDERDEBUG==1) + cout << "cannot activate jack client" << endl; +\#endif + }; +} +\#endif} {} + } + Function {isjackinitialized()} {open private return_type bool + } { + code {if (this->jackclient!=NULL) +{ + return true; +} +return false;} {} + } + Function {portaudioinit()} {open private return_type void + } { + code {\#ifndef LIBPORTAUDIO +return; +\#endif +\#ifdef LIBPORTAUDIO +//if (currsong==NULL) return; +//\#if (RECORDERDEBUG==1) +//cout << "Init portaudio" << endl; +//\#endif +//mustdisplaytimer=true; +PaError err; +err=(*(portaudio->Pa_Initialize))(); +if (err!=paNoError) { + this->portaudiostream=NULL; + (*(portaudio->Pa_Terminate))(); return; +\#if (RECORDERDEBUG==1) +cout << "Error during init portaudio" << endl; +\#endif +} +this->mustloop(false); +this->as_looppos=0; +this->portaudio_initialized=1; +this->as_initialized=1; +\#endif} {} + } + Function {isportaudioinitialized()} {open private return_type bool + } { + code {if (!(portaudio->libloaded)) { +return false; +} +if (portaudiostream!=NULL) { + return true; +} +if (portaudio_initialized!=0) { + return true; +} +return false;} {} + } + Function {portaudio_process(const void *inputBuffer, void *outputBuffer, __uint32 nframes, const PaStreamCallbackTimeInfo* timeinfo,PaStreamCallbackFlags, void *userData)} {open private return_type {static int} + } { + code {RecorderControl* recordercontrol=(RecorderControl*)userData; + +if (recordercontrol==NULL) { + cout << "no control" << endl; + return 0; +} +AudioSystem* audio=recordercontrol->audio; +if (audio==NULL) +{ + cout << "no audiosys" << endl; + return 0; +} +if (audio->portaudio==NULL) +{ + cout << "no portaudio" << endl; + return 0; +} +if (!(audio->portaudio->libloaded)) +{ + cout << "no palib" << endl; + return 0; +} +if (!audio->havestreamtime) +{ + audio->streamtime=0; + audio->havestreamtime=true; +} + +float samleft=0; +float samright=0; + +//hd24fs* myfs=mythis->currenthd24; + +PaStream* curr_pa_stream=audio->portaudiostream; + +if (curr_pa_stream==NULL) +{ + cout << "no stream" << endl; + return paContinue; +} +if ((audio->mtsample)==NULL) +{ + cout << "no sample" << endl; + return paContinue; +} + +// TODO: connect audio system to mixer +MixerControl* mixer=audio->mixer(); +if (mixer==NULL) +{ + cout << "no mixer" << endl; + return paContinue; +} + +if (audio->mustloop()) +{ + cout << "must loop" << endl; + return paContinue; +} + +hd24song* mysong=recordercontrol->song(); +if (mysong == NULL) +{ + cout << "no song" << endl; + return 0;//nothing to do! +} + +unsigned int tottracks=(unsigned int)mysong->logical_channels(); + +/* frame time indicates how long the stream has been playing + and is reset to 0 after pressing stop/play. + To compensate for this, we must add our portaudio-offset, + the offset of the songcursor when we pressed 'play'. + We then record the absolute stream time in pa_streamtime. */ +__sint64 frame_time = audio->streamtime; +frame_time+=audio->portaudiooffset; +//audio->streamtime=frame_time; +audio->streamtime+=nframes; +MixerChannelControl* mixerchannel[24]; + +unsigned int i; +__sint64 intsamval=0; + +mysong->golocatepos(frame_time); +int loopmode=recordercontrol->loopmode(); +int jumpedloop=0; + + __sint64 frpos=frame_time; + __sint64 posoffset=0; + for (i=0;igetlocatepos(hd24song::LOCATEPOS_LOOPEND))) + { + frpos=mysong->getlocatepos(hd24song::LOCATEPOS_LOOPSTART); + mysong->golocatepos(frpos); + posoffset=0; + jumpedloop=1; + } + } + + mysong->getmultitracksample( + (long*)((&audio->mtsample[i*25])), + hd24song::READMODE_REALTIME + ); + // if sample rate is high speed, skip next sample. + if ((mysong->physical_channels()/mysong->logical_channels())==2) + { + mysong->getmultitracksample( + (long*)((&audio->mtsample[i*25])), + hd24song::READMODE_REALTIME + ); + } + } + if (jumpedloop==1) + { + audio->as_looppos=frpos+posoffset; + audio->mustloop(true); + } + + + + for (unsigned int tracknum=0;tracknumparentui()->mixerchannel[tracknum]->control; + } + + for (unsigned int tracknum=0;tracknumdata->trackpeak[tracknum]=0; + } + + + for (i=0;imtsample[i*25+tracknum])); + intsamval=xb[0]; + intsamval=((intsamval>>16)+((intsamval%256)<<16)+(intsamval & 0xff00)); + if (intsamval>=(1<<23)) { + intsamval-=(1<<24); + } + + + if (mysong->istrackmonitoringinput(tracknum+1)) + { + subsamval=((tracknum%2)==0)?(samleft):(samright); + } + else + { + subsamval=(intsamval/(double)0x800000); + } + samvaltot+=subsamval; + if (fabs(subsamval) > recordercontrol->data->trackpeak[tracknum]) { + recordercontrol->data->trackpeak[tracknum]=fabs(subsamval); + } + + mixerchannel[tracknum]->sample(i,subsamval); + + } + if (tottracks<24) { + for (unsigned int tracknum=tottracks;tracknumsample(i,0); + } + } + /* + if (outputBuffer!=NULL) { + ((float*)outputBuffer)[i*2] = samval; // left + ((float*)outputBuffer)[i*2+1] = samval; // right + }*/ + + } + mixer->mix(nframes); + + if (outputBuffer!=NULL) { + + for (i=0;imasterout(0,i); // left + ((float*)outputBuffer)[i*2+1] = mixer->masterout(1,i); // right + } + } + +// cout << mythis->trackpeak[0] << endl; + +return 0;} {} + } + Function {portaudio_transport_start()} {open private return_type void + } { + code {if (!(portaudio->libloaded)) { +return; +} + +\#if (RECORDERDEBUG==1) +cout << "portaudio transport start" << endl; +\#endif +if (!isportaudioinitialized()) +{ + PaError err=(*(portaudio->Pa_Initialize))(); + if (err != paNoError) + { +\#if (RECORDERDEBUG==1) + cout << "Cannot initialize portaudio- exiting." << endl; +\#endif + + } +} +if (isportaudioinitialized() && (portaudiostream!=NULL)) { +\#if (RECORDERDEBUG==1) +cout << "already have stream- done starting" << endl; +\#endif + return; +} +this->mustloop(false); + +this->as_looppos=0; +PaDeviceIndex indev=(*(portaudio->Pa_GetDefaultInputDevice))(); +PaDeviceIndex outdev=(*(portaudio->Pa_GetDefaultOutputDevice))(); +cout << "default input device="<samplerate(); +cout << "trying samrate="<Pa_GetErrorText(err) << endl; +cout << "playbackrate=" << playbackrate << endl; +\#endif + (*(portaudio->Pa_Terminate))(); + return; +} +\#if (RECORDERDEBUG==1) +cout << "Stream opened, going to start it now..." << endl; +\#endif +err=(*(portaudio->Pa_StartStream))(portaudiostream); +if (err!=paNoError) { +\#if (RECORDERDEBUG==1) +cout << "Error starting stream" << endl; +cout << portaudio->Pa_GetErrorText(err) << endl; +\#endif + (*(portaudio->Pa_Terminate))(); + return; +} +\#if (RECORDERDEBUG==1) +cout << "Stream started" << endl; +\#endif + + +return;} {} + } + Function {stopPAstream()} {open private return_type void + } { + code {// only to be called by portaudio_transport_stop +if (portaudiostream==NULL) return; +PaStream* pstream=portaudiostream; +portaudiostream=NULL; + +PaError err = (*(portaudio->Pa_StopStream))( pstream ); + +if (err!=paNoError) { + cout << portaudio->Pa_GetErrorText(err) << endl; +} + +err = (*(portaudio->Pa_CloseStream))( pstream ); + +if (err!=paNoError) { + cout << portaudio->Pa_GetErrorText(err) << endl; +} + +(*(portaudio->Pa_Terminate))();} {} + } + Function {portaudio_transport_stop()} {open private return_type void + } { + code {if (portaudio==NULL) return; +if (!(portaudio->libloaded)) return; + +\#if (RECORDERDEBUG==1) +cout << "portaudio transport stop" << endl; +\#endif +// TODO: only stop stream if not monitoring input. +stopPAstream(); +portaudio_initialized=0; +portaudiostream=NULL; +portaudiooffset+=streamtime; +cout << "portaudiooffset at stop=" << portaudiooffset << endl; +if (mtsample!=NULL) +{ + memutils::myfree("portaudio_transport_stop",mtsample); + mtsample=NULL; +}} {} + } + Function {hd24_transport_goloc(__uint32 frames)} {open return_type void + } { + code {if (libjack!=NULL) +{ + if (libjack->libloaded) { + if (portaudio_initialized!=1) { + + jackinit(); + if (jackclient!=NULL) { + hd24_transport_locate((__sint64)frames); + return; + } + } + } +} + +if (portaudio!=NULL) +{ + if (portaudio->libloaded) + { + hd24_transport_locate((__sint64)frames); + return; + } +}} {} + } + Function {hd24_transport_locate(__sint64 i)} {open return_type void + } { + code {cout << "Request to transport locate to " << i << endl; +if (i<0) i=0; +if (libjack!=NULL) +{ + if (libjack->libloaded) { + cout << "try jackinit" << endl; + jackinit(); + if (jackclient!=NULL) { + libjack->jack_transport_locate(jackclient,i); + return; + } + } + cout << "Jack locate attempt inconclusive, will try portaudio if available" << endl; +} + +if (portaudio!=NULL) +{ + if (portaudio->libloaded) { + cout << "will have to do portaudio locate." << endl; + bool streamwasinitialized=true; + if (!(isportaudioinitialized())) + { + cout << "No previous stream, init a new one "<< endl; + streamwasinitialized=false; + if (tape==NULL) + { + return; + } + + tape->currentlocation((i < 0) ? 0 : i); + cout << "set location to " << i << endl; + portaudiooffset=i; // still ok even without active stream + streamtime=i; + cout << "set portaudiooffset, streamtime to " << i << endl; + return; // <-- see if this does the trick- no previous + // stream, no new one. + } + + PaError err; + if (portaudiostream!=NULL) + { + cout << "Still have a stream that needs stopping first." << endl; + err = (*(portaudio->Pa_StopStream))( portaudiostream ); + if (err!=paNoError) + { + // maybe another program owns the stream. + cout << portaudio->Pa_GetErrorText(err) << endl; + } + + PaStream* oldportaudiostream=portaudiostream; + portaudiostream=NULL; + err = (*(portaudio->Pa_CloseStream))( oldportaudiostream ); + } + + portaudiooffset=i; // still ok even without active stream + streamtime=i; // old portaudio V18 legacy + + bool streamnolongerinitialized=false; + if (!(isportaudioinitialized())) + { + if (streamwasinitialized) + { + streamnolongerinitialized=true; + } + } + + if (streamnolongerinitialized) + { + /* if closing stream means no longer initialized, + do not open another because we are not playing back + anything at the moment. */ + return; + } + cout << "open a fresh stream" << endl; + + PaDeviceIndex indev=(*(portaudio->Pa_GetDefaultInputDevice))(); + PaDeviceIndex outdev=(*(portaudio->Pa_GetDefaultOutputDevice))(); + if (inputParameters!=NULL) + { + memset(inputParameters,'\\0',sizeof(*inputParameters)); + + this->inputParameters->device=indev; + this->inputParameters->channelCount=2; + this->inputParameters->sampleFormat=paFloat32; + void* devinfo=(void*)(*(portaudio->Pa_GetDeviceInfo))( inputParameters->device ); + if (devinfo!=NULL) + { + this->inputParameters->suggestedLatency = (*(portaudio->Pa_GetDeviceInfo))( inputParameters->device )->defaultLowInputLatency; + } + this->inputParameters->hostApiSpecificStreamInfo = NULL; + } + if (outputParameters!=NULL) + { + memset(outputParameters,'\\0',sizeof(*outputParameters)); + this->outputParameters->device=outdev; + this->outputParameters->channelCount=2; + this->outputParameters->sampleFormat=paFloat32; + void* devinfo=(void*)(*(portaudio->Pa_GetDeviceInfo))( outputParameters->device ); + if (devinfo!=NULL) + { + this->outputParameters->suggestedLatency = (*(portaudio->Pa_GetDeviceInfo))( outputParameters->device )->defaultLowOutputLatency; + } + this->outputParameters->hostApiSpecificStreamInfo = NULL; + } + + double samrate=this->samplerate(); + cout << " sample rate for new stream is " << samrate << endl; + if (samrate==0) + { + return; + } + + err=(*(portaudio->Pa_OpenStream))( + &portaudiostream, + NULL,/*this->inputParameters,*/ + this->outputParameters, + samrate, + PA_FRAMESPERBUF, /* frames per buffer */ + paClipOff | paDitherOff, + portaudio_process, + this->recorder); + this->havestreamtime=false; + this->streamtime=0; + + if (err!=paNoError) { + cout << portaudio->Pa_GetErrorText(err) << endl; + } + if (err!=paNoError) { (*( portaudio->Pa_Terminate))(); return; } + + + err=(*(portaudio->Pa_StartStream))(portaudiostream); + if (err!=paNoError) { + cout << portaudio->Pa_GetErrorText(err) << endl; + } + cout << "stream appears to have started successfully" << endl; + + return; + } +}} {} + } + Function {hd24_transport_locate(__uint32 i)} {open return_type void + } { + code {this->hd24_transport_locate((__sint64)i);} {} + } + Function {hd24_transport_start()} {open return_type void + } { + code {if (libjack!=NULL) +{ + if (libjack->libloaded) { + jackinit(); + if (jackclient!=NULL) { + libjack->jack_transport_start(jackclient); + return; + } + } +} + +if (portaudio!=NULL) +{ + if (portaudio->libloaded) + { + if (!(isportaudioinitialized())) + { + portaudioinit(); + } + if (isportaudioinitialized()) + { + portaudio_transport_start(); + return; + } + } +}} {} + } + Function {hd24_transport_stop()} {open return_type void + } { + code {if (recorder!=NULL) +{ + recorder->resetpeaks(); +} + +if (libjack!=NULL) +{ + if (libjack->libloaded) + { + jackinit(); + if (jackclient!=NULL) + { + libjack->jack_transport_stop(jackclient); + return; + } + } +} + +if (portaudio!=NULL) +{ + if (portaudio->libloaded) + { + if (!(isportaudioinitialized())) + { + portaudioinit(); + } + if (isportaudioinitialized()) + { + portaudio_transport_stop(); + return; + } + } +}} {} + } + Function {hd24_transport_ffwd(long int frames)} {open return_type void + } { + code {if (portaudio_initialized!=1) +{ + if (libjack!=NULL) + { + if (libjack->libloaded) + { + jackinit(); + if (jackclient!=NULL) + { + __sint64 frame_time = /* currentlocation() */ + (__sint64)(libjack->jack_get_current_transport_frame(jackclient)); + hd24_transport_locate((__sint64)(frame_time+frames)); + return; + } + } + } +} + +if (portaudio!=NULL) +{ + if (portaudio->libloaded) + { + __sint64 frame_time=currentlocation(); + hd24_transport_locate((__sint64)(frame_time+frames)); + +//string* dur=currsong->display_cursor(); +//setstatus(*dur); +//delete (dur); + + return; + } +}} {} + } + Function {hd24_transport_rew(long int frames)} {open return_type void + } { + code {if (libjack!=NULL) +{ + if (libjack->libloaded) + { + if (portaudio_initialized!=1) + { + jackinit(); + if (jackclient!=NULL) + { + __sint64 frame_time = + (__sint64)(libjack->jack_get_current_transport_frame(jackclient)); + if (frames>frame_time) { + hd24_transport_locate((__sint64)0); + } else { + hd24_transport_locate((__sint64)(frame_time-frames)); + } + return; + } + } + } +} + +if (portaudio!=NULL) +{ + if (portaudio->libloaded) { + + __sint64 frame_time=currentlocation(); + if (frames>frame_time) { + hd24_transport_locate((__sint64)0); + } else { + hd24_transport_locate((__sint64)(frame_time-frames)); + } + + hd24_transport_locate((__sint64)(frame_time-frames)); + + return; + } +}} {} + } + Function {isinitialized()} {return_type bool + } { + code {if (this->isportaudioinitialized()) +{ + return true; +} +if (this->isjackinitialized()) +{ + return true; +} +return false;} {} + } + Function {mustloop()} {return_type bool + } { + code {return this->as_mustloop;} {} + } + Function {mustloop(bool yesno)} {return_type void + } { + code {this->as_mustloop=yesno;} {} + } + Function {samplerate()} {return_type __uint32 + } { + code {return this->samrate; +/*(double)(currsong->samplerate()/(currsong->physical_channels()/currsong->logical_channels())); */} {} + } + Function {samplerate(__uint32 newrate)} {return_type void + } { + code {this->samrate=newrate;} {} + } + Function {looppos()} {return_type __uint32 + } { + code {return this->as_looppos;} {} + } + Function {looppos(__uint32 newpos)} {return_type void + } { + code {this->as_looppos=newpos;} {} + } + Function {locatepoint(int locpointnum,__uint32 locatepos)} {return_type void + } { + code {if (tape==NULL) return; +tape->setlocatepos(locpointnum,locatepos);} {} + } + Function {locatepoint(int locpointnum)} {return_type __uint32 + } { + code {if (tape==NULL) return 0; +return tape->getlocatepos(locpointnum);} {} + } + Function {audiolib(int whichlib,void* libptr)} {open return_type void + } { + code {if (whichlib==AUDIOLIB_PORTAUDIO) +{ + this->portaudio=(PortAudioWrapper*)libptr; +\#if (RECORDERDEBUG==1) +cout << "set portaudio lib to " << libptr << endl; +\#endif + return; +} +if (whichlib==AUDIOLIB_JACK) +{ + this->libjack=(JackWrapper*)libptr; +\#if (RECORDERDEBUG==1) +cout << "set jack lib to " << libptr << endl; +\#endif + return; +} +if (whichlib==AUDIOLIB_SNDFILE) +{ + this->soundfile=(SoundFileWrapper*)libptr; +\#if (RECORDERDEBUG==1) +cout << "set soundfile lib to " << libptr << endl; +\#endif +}} {} + } + Function {audiolib(int whichlib)} {open return_type {void*} + } { + code {if (whichlib==AUDIOLIB_PORTAUDIO) +{ + return (void*)portaudio; +} +if (whichlib==AUDIOLIB_JACK) +{ + return (void*)libjack; +} +if (whichlib==AUDIOLIB_SNDFILE) +{ + return (void*)soundfile; +} +return NULL;} {} + } + Function {~AudioSystem()} {open + } { + code {if (inputParameters!=NULL) +{ + delete inputParameters; + inputParameters=NULL; +} +if (outputParameters!=NULL) +{ + delete outputParameters; + outputParameters=NULL; +} +\#if (RECORDERDEBUG==1) +cout << "AudioSystem::~AudioSystem()" << endl; +\#endif} {} + } + Function {audiostore(AudioStorage* store)} {open return_type void + } { + code {this->tape=store; +if (store!=NULL) +{ + this->samrate=store->samplerate(); +}} {} + } + Function {audiostore()} {open return_type {AudioStorage*} + } { + code {return tape;} {} + } + Function {mixer(MixerControl* p_mixer)} {open return_type void + } { + code {this->mixercontrol=p_mixer;} {} + } + Function {mixer()} {open return_type {MixerControl*} + } { + code {return this->mixercontrol;} {} + } +} + +class RecorderData {open +} { + decl {int loopmode;} {public + } + decl {float trackpeak[24];} {public + } +} + +class RecorderControl {open +} { + decl {RecorderData* data;} {public + } + decl {RecorderUI* ui;} {public + } + decl {AudioSystem* audio;} {public + } + Function {RecorderControl()} {open + } { + code {this->data=new RecorderData(); +init();} {} + } + Function {~RecorderControl()} {open + } { + code {if (this->data!=NULL) +{ + delete this->data; +}} {} + } + Function {init()} {open return_type void + } { + code {this->ui=NULL; +this->audio=new AudioSystem(this); +data->loopmode=0;} {} + } + Function {ready()} {open return_type int + } { + code {return 1;} {} + } + Function {parentui()} {open return_type {RecorderUI*} + } { + code {return this->ui;} {} + } + Function {parentui(RecorderUI* p_ui)} {open return_type void + } { + code {this->ui=p_ui;} {} + } + Function {loopmode()} {open return_type int + } { + code {return data->loopmode;} {} + } + Function {loopmode(int p_loopmode)} {return_type void + } { + code {data->loopmode=p_loopmode; +if (ui!=NULL) +{ + ui->button_loopmode->value(p_loopmode); + ui->button_loopmode->redraw(); +}} {} + } + Function {button_scrub_call(int amount,RecorderControl* mycontrol)} {open return_type {static void} + } { + code {if (mycontrol->audio==NULL) return; +// we could get the current transport pos here; .... +if (amount>0) { +mycontrol->audio->hd24_transport_ffwd((__uint32)(300*amount)); +} else { +mycontrol->audio->hd24_transport_rew((__uint32)(-300*amount)); +} +// ... then the new transport pos here; read the snippet +// of audio that is spanned by the difference, stretch +// it to the audio buffer size, then play it. +// Alternatively, a visual-only representation could be fine.} {} + } + Function {button_rew_call()} {open return_type void + } { + code {if (this->audio==NULL) return; +this->audio->hd24_transport_rew(5*this->audio->samplerate());} {} + } + Function {button_ffwd_call()} {open return_type void + } { + code {if (this->audio==NULL) return; +this->audio->hd24_transport_ffwd(5*this->audio->samplerate());} {} + } + Function {button_stop_call()} {open return_type void + } { + code {if (this->audio==NULL) return; +//this->currenthd24->settransportstatus(hd24fs::TRANSPORTSTATUS_STOP); +//TODO: The above is for monitoring purposes +this->audio->hd24_transport_stop(); +if (ui==NULL) return; + +ui->button_light((void*)(ui->button_stop),1); +//button_stop->up_image(button_stop_uplit->image()); +ui->button_up((void*)(ui->button_play)); +ui->button_up((void*)(ui->button_rec));} {} + } + Function {button_play_call()} {open return_type void + } { + code {if (this->audio==NULL) return; +//if (button_rec->value()==1) { +// this->currenthd24->settransportstatus(hd24fs::TRANSPORTSTATUS_REC); +// TODO: The above is for monitoring purposes +//} else { +// this->currenthd24->settransportstatus(hd24fs::TRANSPORTSTATUS_PLAY); +// TODO: The above is for monitoring purposes +//} +this->audio->hd24_transport_start(); + +ui->button_light(ui->button_stop,0); + +if (ui->button_play->value()==1) +{ + ui->button_up(ui->button_rec); +} +ui->button_down(ui->button_play);} {} + } + Function {button_rec_call()} {open return_type void + } { + code {/* ui->button_rec->redraw(); +if (currsong==NULL) return; +if (currenthd24==NULL) return; + +if (this->currenthd24->gettransportstatus()==hd24fs::TRANSPORTSTATUS_STOP) { + return; +} + +if (ui->button_rec->value()==1) { + this->currenthd24->settransportstatus(hd24fs::TRANSPORTSTATUS_REC); +} else { + this->currenthd24->settransportstatus(hd24fs::TRANSPORTSTATUS_PLAY); +} + +this->audio->hd24_transport_stop(); +//button_play->value(0); */} {} + } + Function {solo(int channel,int val)} {} { + code {// set solo status of channel to value +//mixer->mixerchannel[channel]->control->solo(val);} {} + } + Function {mute(int channel,int val)} {} { + code {// set mute status of channel to value +//mixer->mixerchannel[channel]->control->mute(val);} {} + } + Function {resetpeaks()} {open return_type void + } { + code {for (int i=0;i<24;i++) +{ + data->trackpeak[i]=0; +}} {} + } + Function {highlight_setbuttons(int value)} {open return_type void + } { + code {ui->highlight_setbuttons(value);} {} + } + Function {hd24_transport_goloc(__uint32 frames)} {open return_type void + } { + code {if (audio==NULL) +{ + return; +} +audio->hd24_transport_goloc(frames);} {} + } + Function {button_rehearse_call()} {return_type void + } { + code {return;} {} + } + Function {handlelocatebutton(__uint32 locpoint)} {return_type void + } { + code {// either set or jumpto locate point + +if (ui->button_setlocate->value()==1) +{ + // set locate point + ui->button_setlocate->value(0); + highlight_setbuttons(ui->button_setlocate->value()); + // set loop start to current song cursor + if (audio==NULL) return; + audio->locatepoint(locpoint,audio->currentlocation()); +// ui->populate_locatepoints(currsong,ui->locatepoints); +} else { + // jump to locate point + if (audio==NULL) return; + audio->hd24_transport_locate((__sint64)(audio->locatepoint(locpoint))); +}} {} + } + Function {disable()} {} { + code {/* Disable the recorder */ +//fl_message("TODO: recordercontrol::disable()"); +if ((this->ui)==NULL) return; +this->ui->deactivate();} {} + } + Function {enable()} {} { + code {/* Disable the recorder */ +//fl_message("TODO: recordercontrol::enable()"); +if ((this->ui)==NULL) return; +this->ui->activate();} {} + } + decl {int dispwritecountdown;} {public + } + Function {dispwrite(unsigned int line,const char* message)} {return_type void + } { + code {ui->dispwrite(line,message);} {} + } + Function {dispwrite(unsigned int line,const char* message,__uint32 timeout_msec)} {return_type void + } { + code {ui->dispwrite(line,message,timeout_msec);} {} + } + Function {audiolib(int whichlib,void* libptr)} {open return_type void + } { + code {if (audio==NULL) return; +audio->audiolib(whichlib,libptr);} {} + } + Function {song(hd24song* store)} {open return_type void + } { + code {audio->audiostore((AudioStorage*)store); +if (store!=NULL) +{ + this->enable(); +} else { + this->disable(); +} +if (store==NULL) +{ + string* disp=new string(" No Song " + " Selected "); + dispwrite(0,disp->c_str()); + delete disp; +} +else +{ + + string disp="S"; + string* idstr=Convert::int2str(store->songid(),2,"0"); + disp+=*idstr; + delete idstr; + disp+=":\\""; + string* dummy=store->songname(); + //transfersource->value(dummy->c_str()); + string* dummy2=Convert::readstring((unsigned char*)dummy->c_str(),0,10); + string* dummy3=Convert::readstring((unsigned char*)dummy->c_str(),0,11); + + disp+=*dummy2; + delete dummy; + delete dummy2; + if (dummy3->length()>10) + { + disp+="\\4"; // arrow right + } else { + disp+="\\""; + } + delete dummy3; + string* disp2=Convert::padright(disp,16," "); + + string* dur=store->display_duration(); + + *disp2+=dur->substr(0,8); + *disp2+=":"; + *disp2+=dur->substr(9,2); + *disp2+=" "; + delete dur; + + if (store->iswriteprotected()) + { + *disp2+="\\1"; + } else { + *disp2+="\\2"; + } + string* strtracksb=Convert::int2str(store->logical_channels(),2,"0"); + *disp2+=*strtracksb; + delete strtracksb; + *disp2+="t"; + + dispwrite(0,disp2->c_str()); + delete disp2; + +}} {selected + } + } + Function {song()} {open return_type {hd24song*} + } { + code {return (hd24song*)audio->audiostore();} {} + } + Function {toggletrackarmed(__uint32 base1tracknum)} {open return_type void + } { + code {AudioStorage* astore=(hd24song*)(this->audio->audiostore()); +astore->trackarmed(base1tracknum,!astore->trackarmed(base1tracknum));} {} + } +} + +class RecorderUI {: {public Fl_Group} +} { + decl {RecorderControl* control;} {public + } + Function {RecorderUI(int a,int b,int c,int d):Fl_Group(a,b,c,d,NULL)} {open + } { + code {this->control=new RecorderControl(); +control->parentui(this); +this->window=(Fl_Window*)(this->make_window()); +this->init_gui();} {} + } + Function {~RecorderUI()} {open + } { + code {delete control;} {} + } + Function {init_gui()} {open + } { + code {// position vu meters on recorder tab +int startx=trackchan[0]->x(); +int starty=trackchan[0]->y(); +for (unsigned int i=1; i<=MAXCHANNELS; i++) { + int coloff=((i-((i-1)%8))-1)/8; + trackchan[i-1]->setui(this); + trackchan[i-1]->position(7+(18*coloff)+(startx)+((i-1)*23),starty+10); + trackchan[i-1]->setchnum(i); + + solobutton[i-1]->position(8+(15*coloff)+(startx)+((i-1)*23),solobutton[i-1]->y()); + solobutton[i-1]->size(solobutton[0]->w(),solobutton[0]->h()); + solobutton[i-1]->up_image(solobutton[0]->up_image()); + solobutton[i-1]->down_image(solobutton[0]->down_image()); + mutebutton[i-1]->up_image(mutebutton[0]->up_image()); + mutebutton[i-1]->down_image(mutebutton[0]->down_image()); + mutebutton[i-1]->position(solobutton[i-1]->x(),mutebutton[i-1]->y()); + mutebutton[i-1]->size(mutebutton[0]->w(),mutebutton[0]->h()); + + armbutton[i-1]->position(solobutton[i-1]->x(),armbutton[i-1]->y()); + if (i!=1) { + armbutton[i-1]->size(armbutton[0]->w(),armbutton[0]->h()); + armbutton[i-1]->up_image(armbutton[0]->up_image()); + armbutton[i-1]->down_image(armbutton[0]->down_image()); + } + +} + + +trackinfo[0]->position(8*23+15,starty+10); +trackinfo[1]->position(16*23+33,starty+10);} {} + } + Function {set_ui(HD24UserInterface* p_ui)} {open return_type void + } { + code {this->ui=p_ui;} {} + } + decl {bool mustdisplaytimer;} {public + } + decl {int loopmode;} {public + } + decl {RecorderChannelUI* recorderchannel[24];} {public + } + decl {/* ==== RECORDER UI STUFF ====================*/} {} + decl {HD24UserInterface* ui;} {} + decl {//hd24fs* currenthd24;} {public + } + decl {//hd24song* currsong;} {public + } + decl {Fl_Window* window} {} + decl {int currpeakmode;} {public + } + decl {Fl_Box* dispcell[16][2];} {public + } + decl {Fl_Box* i7seg[10];} {public + } + decl {Fl_Box* dispfont[256];} {public + } + decl {int slidermoved;} {public + } + decl {Fl_Image_Button* armbutton[24];} {public + } + decl {Fl_Image_Toggle_Button* mutebutton[24];} {public + } + decl {Fl_Image_Toggle_Button* solobutton[24];} {public + } + decl {int blinkcounter; /* For blinking record enable leds of level meters etc */} {public + } + decl {HD24TrackChannel* trackchan[24];} {public + } + decl {TrackInfo* trackinfo[24];} {public + } + decl {char olddisp[32];} {} + Function {dispwrite_raw(unsigned int line,const char* message,bool savedisp)} {private return_type void + } { + code {unsigned int max=strlen(message); +// allowed lines on display: 0 and 1 +if (line>1) { return; } + +if (max>(16*(2-line))) { + // maximum 16 chars if we start on line 1 (second line) + // 32 chars if we start on line 0 (first line). + max=(16*(2-line)); +} + +for (unsigned int i=0;idispcell[i%16][line]->image(dispfont[currchar]->image()); + this->dispcell[i%16][line]->redraw(); + +} +fl_check();} {} + } + decl {int dispwritecountdown;} {public + } + Function {dispwrite(unsigned int line,const char* message)} {return_type void + } { + code {dispwrite_raw(line,message,true); +dispwritecountdown=0;} {} + } + Function {disprestore()} {return_type void + } { + code {dispwrite_raw(0,&olddisp[0],false); +dispwritecountdown=0;} {} + } + Function {dispwrite(unsigned int line,const char* message,__uint32 timeout_msec)} {return_type void + } { + code {dispwrite_raw(line,message,false); + dispwritecountdown=(int)(1000*TIMEOUT);} {} + } + Function {readmixer()} {open return_type void + } { + code {// set solo status of channel to value +/* +for (unsigned int i=0;ivalue(mixer->mixerchannel[i]->control->solo()); + solobutton[i]->redraw(); + mutebutton[i]->value(mixer->mixerchannel[i]->control->mute()); + mutebutton[i]->redraw(); +} +*/} {} + } + Function {make_window() /*<-----------------------------------*/} {open + } { + Fl_Window recordergroup {open + xywh {378 259 615 440} type Double + code0 {o->position(this->x(),this->y());} + class Fl_Group visible + } { + Fl_Group resources {open + xywh {25 62 560 423} hide deactivate + } { + Fl_Button button_play_up { + tooltip Play image {images/button_play.gif} xywh {25 75 50 30} labelsize 11 align 16 deactivate + } + Fl_Button button_play_dn { + tooltip Play image {images/button_play_dn.gif} xywh {75 75 50 30} labelsize 11 align 16 deactivate + } + Fl_Button button_stop_dn { + tooltip Play image {images/button_stop_dn.gif} xywh {295 445 50 30} labelsize 11 align 16 deactivate + } + Fl_Button button_stop_up { + tooltip Play image {images/button_stop.gif} xywh {345 445 50 30} labelsize 11 align 16 deactivate + } + Fl_Button button_stop_uplit { + tooltip Play image {images/button_stop_uplit.gif} xywh {355 455 50 30} labelsize 11 align 16 deactivate + } + Fl_Button button_small_up { + tooltip arm image {images/button_small.gif} xywh {565 195 20 15} deactivate + } + Fl_Button button_small_dn { + tooltip arm image {images/button_small_dn.gif} xywh {60 215 20 15} deactivate + } + Fl_Button button_rew_up { + tooltip Play image {images/button_rew.gif} xywh {35 85 50 30} labelsize 11 align 16 deactivate + } + Fl_Button button_rew_dn { + tooltip Play image {images/button_rew_dn.gif} xywh {85 85 50 30} labelsize 11 align 16 deactivate + } + Fl_Button button_ffwd_up { + tooltip Play image {images/button_ffwd.gif} xywh {45 95 50 30} labelsize 11 align 16 deactivate + } + Fl_Button button_ffwd_dn { + tooltip Play image {images/button_ffwd_dn.gif} xywh {95 95 50 30} labelsize 11 align 16 deactivate + } + Fl_Button button_rec_up { + tooltip Play image {images/button_rec.gif} xywh {55 105 50 30} labelsize 11 align 16 deactivate + } + Fl_Button button_rec_dn { + tooltip Play image {images/button_rec_dn.gif} xywh {105 105 50 30} labelsize 11 align 16 deactivate + } + Fl_Button button_mute_up { + tooltip Play image {images/button_mute.gif} xywh {65 115 50 30} labelsize 11 align 16 deactivate + } + Fl_Button button_mute_dn { + tooltip Play image {images/button_mute_dn.gif} xywh {115 115 50 30} labelsize 11 align 16 deactivate + } + Fl_Button button_solo_up { + tooltip Play image {images/button_solo.gif} xywh {75 125 50 30} labelsize 11 align 16 deactivate + } + Fl_Button button_solo_dn { + tooltip Play image {images/button_solo_dn.gif} xywh {125 125 50 30} labelsize 11 align 16 deactivate + } + Fl_Button button_lrc_led_up { + tooltip Play image {images/button_lrc_led.gif} xywh {85 135 50 30} labelsize 11 align 16 deactivate + } + Fl_Button button_lrc_led_dn { + tooltip Play image {images/button_lrc_led_dn.gif} xywh {135 135 50 30} labelsize 11 align 16 deactivate + } + Fl_Button button_lrc_led_on_up { + tooltip Play image {images/button_lrc_led_on.gif} xywh {85 135 50 30} labelsize 11 align 16 deactivate + } + Fl_Button button_lrc_led_on_dn { + tooltip Play image {images/button_lrc_led_on_dn.gif} xywh {135 135 50 30} labelsize 11 align 16 deactivate + } + Fl_Button button_lrc_up { + tooltip Play image {images/button_lrc.gif} xywh {85 135 50 30} labelsize 11 align 16 deactivate + } + Fl_Button button_lrc_dn { + tooltip Play image {images/button_lrc_dn.gif} xywh {135 135 50 30} labelsize 11 align 16 deactivate + } + Fl_Box i7seg0 { + image {images/7seg_0.gif} xywh {325 276 20 34} hide + code0 {i7seg[0]=o;} + } + Fl_Box i7seg1 { + image {images/7seg_1.gif} xywh {325 276 20 34} hide + code0 {i7seg[1]=o;} + } + Fl_Box i7seg2 { + image {images/7seg_2.gif} xywh {325 276 20 34} hide + code0 {i7seg[2]=o;} + } + Fl_Box i7seg3 { + image {images/7seg_3.gif} xywh {325 276 20 34} hide + code0 {i7seg[3]=o;} + } + Fl_Box i7seg4 { + image {images/7seg_4.gif} xywh {325 276 20 34} hide + code0 {i7seg[4]=o;} + } + Fl_Box i7seg5 { + image {images/7seg_5.gif} xywh {325 276 20 34} hide + code0 {i7seg[5]=o;} + } + Fl_Box i7seg6 { + image {images/7seg_6.gif} xywh {325 276 20 34} hide + code0 {i7seg[6]=o;} + } + Fl_Box i7seg7 { + image {images/7seg_7.gif} xywh {325 276 20 34} hide + code0 {i7seg[7]=o;} + } + Fl_Box i7seg8 { + image {images/7seg_8.gif} xywh {325 276 20 34} hide + code0 {i7seg[8]=o;} + } + Fl_Box i7seg9 { + image {images/7seg_9.gif} xywh {325 276 20 34} hide + code0 {i7seg[9]=o;} + } + Fl_Group dispfontgroup { + label font open + xywh {565 28 70 52} hide deactivate + } { + Fl_Box {} { + label label + image {images/HD24_matrix_32.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[32]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_33.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[33]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_34.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[34]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_35.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[35]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_36.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[36]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_37.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[37]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_38.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[38]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_39.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[39]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_40.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[40]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_41.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[41]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_42.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[42]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_43.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[43]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_44.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[44]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_45.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[45]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_46.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[46]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_47.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[47]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_48.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[48]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_49.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[49]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_50.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[50]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_51.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[51]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_52.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[52]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_53.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[53]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_54.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[54]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_55.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[55]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_56.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[56]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_57.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[57]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_58.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[58]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_59.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[59]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_60.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[60]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_61.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[61]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_62.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[62]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_63.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[63]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_64.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[64]=o;} + } + Fl_Box {} { + label A + image {images/HD24_matrix_65.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[65]=o;} + } + Fl_Box {} { + label B + image {images/HD24_matrix_66.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[66]=o;} + } + Fl_Box {} { + label C + image {images/HD24_matrix_67.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[67]=o;} + } + Fl_Box {} { + label D + image {images/HD24_matrix_68.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[68]=o;} + } + Fl_Box {} { + label E + image {images/HD24_matrix_69.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[69]=o;} + } + Fl_Box {} { + label F + image {images/HD24_matrix_70.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[70]=o;} + } + Fl_Box {} { + label G + image {images/HD24_matrix_71.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[71]=o;} + } + Fl_Box {} { + label H + image {images/HD24_matrix_72.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[72]=o;} + } + Fl_Box {} { + label I + image {images/HD24_matrix_73.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[73]=o;} + } + Fl_Box {} { + label J + image {images/HD24_matrix_74.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[74]=o;} + } + Fl_Box {} { + label K + image {images/HD24_matrix_75.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[75]=o;} + } + Fl_Box {} { + label L + image {images/HD24_matrix_76.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[76]=o;} + } + Fl_Box {} { + label M + image {images/HD24_matrix_77.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[77]=o;} + } + Fl_Box {} { + label N + image {images/HD24_matrix_78.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[78]=o;} + } + Fl_Box {} { + label O + image {images/HD24_matrix_79.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[79]=o;} + } + Fl_Box {} { + label P + image {images/HD24_matrix_80.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[80]=o;} + } + Fl_Box {} { + label Q + image {images/HD24_matrix_81.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[81]=o;} + } + Fl_Box {} { + label R + image {images/HD24_matrix_82.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[82]=o;} + } + Fl_Box {} { + label S + image {images/HD24_matrix_83.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[83]=o;} + } + Fl_Box {} { + label T + image {images/HD24_matrix_84.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[84]=o;} + } + Fl_Box {} { + label U + image {images/HD24_matrix_85.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[85]=o;} + } + Fl_Box {} { + label V + image {images/HD24_matrix_86.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[86]=o;} + } + Fl_Box {} { + label W + image {images/HD24_matrix_87.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[87]=o;} + } + Fl_Box {} { + label X + image {images/HD24_matrix_88.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[88]=o;} + } + Fl_Box {} { + label Y + image {images/HD24_matrix_89.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[89]=o;} + } + Fl_Box {} { + label Z + image {images/HD24_matrix_90.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[90]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_91.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[91]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_92.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[92]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_93.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[93]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_94.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[94]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_95.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[95]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_96.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[96]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_97.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[97]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_98.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[98]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_99.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[99]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_100.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[100]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_101.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[101]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_102.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[102]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_103.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[103]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_104.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[104]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_105.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[105]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_106.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[106]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_107.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[107]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_108.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[108]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_109.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[109]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_110.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[110]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_111.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[111]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_112.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[112]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_113.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[113]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_114.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[114]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_115.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[115]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_116.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[116]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_117.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[117]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_118.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[118]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_119.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[119]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_120.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[120]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_121.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[121]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_122.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[122]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_123.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[123]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_124.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[124]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_125.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[125]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_126.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[126]=o;} + } + Fl_Box {} { + label label + image {images/HD24_matrix_127.gif} xywh {580 43 35 17} hide + code0 {this->dispfont[127]=o;} + } + Fl_Box {} { + label writeprotect + image {images/HD24_matrix_writeprotected.gif} xywh {590 53 35 17} hide + code0 {this->dispfont[1]=o;} + } + Fl_Box {} { + label writeenable + image {images/HD24_matrix_writeenabled.gif} xywh {600 63 35 17} hide + code0 {this->dispfont[2]=o;} + } + Fl_Box {} { + label {arrow left} + image {images/HD24_matrix_arrowleft.gif} xywh {600 63 35 17} hide + code0 {this->dispfont[3]=o;} + } + Fl_Box {} { + label {arrow right} + image {images/HD24_matrix_arrowright.gif} xywh {610 73 35 17} hide + code0 {this->dispfont[4]=o;} + } + } + } + Fl_Slider locationslider { + callback {hd24song* currsong=(hd24song*)(this->control->song()); +if (currsong==NULL) return; +this->slidermoved=3; +long long newpos=(long long)currsong->songlength_in_samples(); +newpos*=(int)(o->value()); +newpos=(__uint32)(newpos/1000); +control->hd24_transport_goloc(newpos);} + xywh {10 208 595 17} type Horizontal selection_color 41 labelsize 12 align 4 maximum 1000 step 1 + code0 {this->slidermoved=0;} + } + Fl_Box {} { + xywh {305 226 300 149} box DOWN_BOX color 8 + } + Fl_Button button_setlocate { + label {SET LOC} + callback {control->highlight_setbuttons(o->value());} + 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 + code0 {o->up_image(button_lrc_up->image()); o->down_image(button_lrc_dn->image());} + class Fl_Image_Toggle_Button + } + Fl_Button button_loopmode { + label {AUTO LOOP} + callback {control->loopmode(button_loopmode->value());} + 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 + code0 {o->up_image(button_lrc_up->image()); o->down_image(button_lrc_dn->image());} + class Fl_Image_Toggle_Button + } + Fl_Repeat_Button button_rew { + callback {control->button_rew_call();} + tooltip Rewind image {images/button_rew.gif} xywh {310 330 50 30} box FLAT_BOX labelsize 11 align 16 + code0 {o->up_image(o->image()); o->down_image(button_rew_dn->image()); o->image(NULL);} + class Fl_Image_Repeat_Button + } + Fl_Repeat_Button button_ffwd { + callback {control->button_ffwd_call();} + tooltip {F Fwd} image {images/button_ffwd.gif} xywh {370 330 50 30} box FLAT_BOX labelsize 11 align 16 + code0 {o->up_image(o->image()); o->down_image(button_ffwd_dn->image()); o->image(NULL);} + class Fl_Image_Repeat_Button + } + Fl_Button button_stop { + callback {if (control!=NULL) control->button_stop_call();} + tooltip Stop image {images/button_stop_uplit.gif} xywh {430 330 50 30} box FLAT_BOX labelsize 11 align 16 + code0 {//o->up_image(button_stop_uplit->image()); o->down_image(button_stop_dn->image());} + code1 {o->up_image(o->image()); o->down_image(button_stop_dn->image()); o->image(NULL);} + class Fl_Image_Button + } + Fl_Button button_play { + callback {control->button_play_call();} + tooltip Play image {images/button_play.gif} xywh {490 330 50 30} box FLAT_BOX labelsize 11 align 16 + code0 {o->up_image(o->image()); o->down_image(button_play_dn->image()); o->image(NULL);} + class Fl_Image_Button + } + Fl_Box {} { + xywh {475 231 127 84} box BORDER_BOX color 0 + } + Fl_Button button_loopstart { + label {LOOP START} + callback {control->handlelocatebutton(hd24song::LOCATEPOS_LOOPSTART);} + 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 + code0 {hlbuttons_defaultcolor=o->color(); o->up_image(button_lrc_led_up->image()); o->down_image(button_lrc_led_dn->image());} + class Fl_Image_Button + } + Fl_Button button_loopend { + label {LOOP END} + callback {control->handlelocatebutton(hd24song::LOCATEPOS_LOOPEND);} + 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 + code0 {o->up_image(button_lrc_led_up->image()); o->down_image(button_lrc_led_dn->image());} + class Fl_Image_Button + } + Fl_Button button_locate0 { + label {LOC 0} + callback {control->audio->hd24_transport_locate((__sint64)0);} + tooltip {Locate 0} xywh {420 250 50 20} box FLAT_BOX color 16 selection_color 18 labelfont 1 labelsize 9 labelcolor 7 align 5 + code0 {o->up_image(button_lrc_up->image()); o->down_image(button_lrc_dn->image());} + class Fl_Image_Button + } + Fl_Button button_rec { + callback {control->button_rec_call();} + tooltip Record image {images/button_rec.gif} xywh {550 330 50 30} type Toggle box FLAT_BOX labelsize 11 + code0 {o->up_image(o->image()); o->down_image(button_rec_dn->image()); o->image(NULL);} + class Fl_Image_Toggle_Button + } + Fl_Group channelcanvas {open + xywh {10 15 595 140} box DOWN_BOX color 0 + } { + Fl_Group tc1 {open + xywh {15 15 15 135} + code0 {trackchan[0]=o;} + class HD24TrackChannel + } {} + Fl_Group tc2 {open + xywh {15 15 15 135} + code0 {trackchan[1]=o;} + class HD24TrackChannel + } {} + Fl_Group tc3 {open + xywh {15 15 15 135} + code0 {trackchan[2]=o;} + class HD24TrackChannel + } {} + Fl_Group tc4 {open + xywh {15 15 15 135} + code0 {trackchan[3]=o;} + class HD24TrackChannel + } {} + Fl_Group tc5 {open + xywh {15 15 15 135} + code0 {trackchan[4]=o;} + class HD24TrackChannel + } {} + Fl_Group tc6 {open + xywh {15 15 15 135} + code0 {trackchan[5]=o;} + class HD24TrackChannel + } {} + Fl_Group tc7 {open + xywh {15 15 15 135} + code0 {trackchan[6]=o;} + class HD24TrackChannel + } {} + Fl_Group tc8 {open + xywh {15 15 15 135} + code0 {trackchan[7]=o;} + class HD24TrackChannel + } {} + Fl_Group trackinfo1 {open + xywh {15 15 15 135} + code0 {trackinfo[0]=trackinfo1;} + class TrackInfo + } {} + Fl_Group tc9 {open + xywh {15 15 15 135} + code0 {trackchan[8]=o;} + class HD24TrackChannel + } {} + Fl_Group tc10 {open + xywh {15 15 15 135} + code0 {trackchan[9]=o;} + class HD24TrackChannel + } {} + Fl_Group tc11 {open + xywh {15 15 15 135} + code0 {trackchan[10]=o;} + class HD24TrackChannel + } {} + Fl_Group tc12 {open + xywh {15 15 15 135} + code0 {trackchan[11]=o;} + class HD24TrackChannel + } {} + Fl_Group tc13 {open + xywh {15 15 15 135} + code0 {trackchan[12]=o;} + class HD24TrackChannel + } {} + Fl_Group tc14 {open + xywh {15 15 15 135} + code0 {trackchan[13]=o;} + class HD24TrackChannel + } {} + Fl_Group tc15 {open + xywh {15 15 15 135} + code0 {trackchan[14]=o;} + class HD24TrackChannel + } {} + Fl_Group tc16 {open + xywh {15 15 15 135} + code0 {trackchan[15]=o;} + class HD24TrackChannel + } {} + Fl_Group trackinfo2 {open + xywh {15 15 15 135} + code0 {trackinfo[1]=trackinfo2;} + class TrackInfo + } {} + Fl_Group tc17 {open + xywh {15 15 15 135} + code0 {trackchan[16]=o;} + class HD24TrackChannel + } {} + Fl_Group tc18 {open + xywh {15 15 15 135} + code0 {trackchan[17]=o;} + class HD24TrackChannel + } {} + Fl_Group tc19 {open + xywh {15 15 15 135} + code0 {trackchan[18]=o;} + class HD24TrackChannel + } {} + Fl_Group tc20 {open + xywh {15 15 15 135} + code0 {trackchan[19]=o;} + class HD24TrackChannel + } {} + Fl_Group tc21 {open + xywh {15 15 15 135} + code0 {trackchan[20]=o;} + class HD24TrackChannel + } {} + Fl_Group tc22 {open + xywh {15 15 15 135} + code0 {trackchan[21]=o;} + class HD24TrackChannel + } {} + Fl_Group tc23 {open + xywh {15 15 15 135} + code0 {trackchan[22]=o;} + class HD24TrackChannel + } {} + Fl_Group tc24 {open + xywh {15 15 15 135} + code0 {trackchan[23]=o;} + class HD24TrackChannel + } {} + Fl_Group {} {open + xywh {35 40 15 15} + } {} + } + Fl_Button arm1 { + callback {this->control->toggletrackarmed(1);} + tooltip arm xywh {40 155 20 15} labelsize 8 labelcolor 7 + code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[0]=o;} + class Fl_Image_Button + } + Fl_Button arm2 { + callback {this->control->toggletrackarmed(2);} + tooltip arm xywh {60 155 15 15} + code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[1]=o;} + class Fl_Image_Button + } + Fl_Button arm3 { + callback {this->control->toggletrackarmed(3);} + tooltip arm xywh {75 155 15 15} + code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[2]=o;} + class Fl_Image_Button + } + Fl_Button arm4 { + callback {this->control->toggletrackarmed(4);} + tooltip arm xywh {90 155 15 15} + code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[3]=o;} + class Fl_Image_Button + } + Fl_Button arm5 { + callback {this->control->toggletrackarmed(5);} + tooltip arm xywh {105 155 15 15} + code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[4]=o;} + class Fl_Image_Button + } + Fl_Button arm6 { + callback {this->control->toggletrackarmed(6);} + tooltip arm xywh {120 155 15 15} + code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[5]=o;} + class Fl_Image_Button + } + Fl_Button arm7 { + callback {this->control->toggletrackarmed(7);} + tooltip arm xywh {135 155 15 15} + code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[6]=o;} + class Fl_Image_Button + } + Fl_Button arm8 { + callback {this->control->toggletrackarmed(8);} + tooltip arm xywh {150 155 15 15} + code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[7]=o;} + class Fl_Image_Button + } + Fl_Button arm9 { + callback {this->control->toggletrackarmed(9);} + tooltip arm xywh {235 155 15 15} + code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[8]=o;} + class Fl_Image_Button + } + Fl_Button arm10 { + callback {this->control->toggletrackarmed(10);} + tooltip arm xywh {250 155 15 15} + code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[9]=o;} + class Fl_Image_Button + } + Fl_Button arm11 { + callback {this->control->toggletrackarmed(11);} + tooltip arm xywh {265 155 15 15} + code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[10]=o;} + class Fl_Image_Button + } + Fl_Button arm12 { + callback {this->control->toggletrackarmed(12);} + tooltip arm xywh {280 155 15 15} + code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[11]=o;} + class Fl_Image_Button + } + Fl_Button arm13 { + callback {this->control->toggletrackarmed(13);} + tooltip arm xywh {295 155 15 15} + code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[12]=o;} + class Fl_Image_Button + } + Fl_Button arm14 { + callback {this->control->toggletrackarmed(14);} + tooltip arm xywh {310 155 15 15} + code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[13]=o;} + class Fl_Image_Button + } + Fl_Button arm15 { + callback {this->control->toggletrackarmed(15);} + tooltip arm xywh {325 155 15 15} + code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[14]=o;} + class Fl_Image_Button + } + Fl_Button arm16 { + callback {this->control->toggletrackarmed(16);} + tooltip arm xywh {340 155 15 15} + code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[15]=o;} + class Fl_Image_Button + } + Fl_Button arm17 { + callback {this->control->toggletrackarmed(17);} + tooltip arm xywh {430 155 15 15} + code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[16]=o;} + class Fl_Image_Button + } + Fl_Button arm18 { + callback {this->control->toggletrackarmed(18);} + tooltip arm xywh {445 155 15 15} + code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[17]=o;} + class Fl_Image_Button + } + Fl_Button arm19 { + callback {this->control->toggletrackarmed(19);} + tooltip arm xywh {460 155 15 15} + code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[18]=o;} + class Fl_Image_Button + } + Fl_Button arm20 { + callback {this->control->toggletrackarmed(20);} + tooltip arm xywh {475 155 15 15} + code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[19]=o;} + class Fl_Image_Button + } + Fl_Button arm21 { + callback {this->control->toggletrackarmed(21);} + tooltip arm xywh {490 155 15 15} + code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[20]=o;} + class Fl_Image_Button + } + Fl_Button arm22 { + callback {this->control->toggletrackarmed(22);} + tooltip arm xywh {505 155 15 15} + code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[21]=o;} + class Fl_Image_Button + } + Fl_Button arm23 { + callback {this->control->toggletrackarmed(23);} + tooltip arm xywh {520 155 15 15} + code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[22]=o;} + class Fl_Image_Button + } + Fl_Button arm24 { + callback {this->control->toggletrackarmed(24);} + tooltip arm xywh {535 155 15 15} + code0 {o->up_image(button_small_up->image()); o->down_image(button_small_dn->image()); armbutton[23]=o;} + class Fl_Image_Button + } + Fl_Button solo1 { + callback {control->solo(0,o->value());} + xywh {40 175 20 15} selection_color 2 + code0 {o->up_image(button_solo_up->image()); o->down_image(button_solo_dn->image()); solobutton[0]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button solo2 { + callback {control->solo(1,o->value());} + xywh {60 175 15 15} selection_color 2 + code0 {solobutton[1]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button solo3 { + callback {control->solo(2,o->value());} + xywh {75 175 15 15} selection_color 2 + code0 {solobutton[2]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button solo4 { + callback {control->solo(3,o->value());} + xywh {90 175 15 15} selection_color 2 + code0 {solobutton[3]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button solo5 { + callback {control->solo(4,o->value());} + xywh {105 175 15 15} selection_color 2 + code0 {solobutton[4]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button solo6 { + callback {control->solo(5,o->value());} + xywh {120 175 15 15} selection_color 2 + code0 {solobutton[5]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button solo7 { + callback {control->solo(6,o->value());} + xywh {135 175 15 15} selection_color 2 + code0 {solobutton[6]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button solo8 { + callback {control->solo(7,o->value());} + xywh {150 175 15 15} selection_color 2 + code0 {solobutton[7]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button solo9 { + callback {control->solo(8,o->value());} + xywh {235 175 15 15} selection_color 2 + code0 {solobutton[8]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button solo10 { + callback {control->solo(9,o->value());} + xywh {250 175 15 15} selection_color 2 + code0 {solobutton[9]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button solo11 { + callback {control->solo(10,o->value());} + xywh {265 175 15 15} selection_color 2 + code0 {solobutton[10]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button solo12 { + callback {control->solo(11,o->value());} + xywh {280 175 15 15} selection_color 2 + code0 {solobutton[11]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button solo13 { + callback {control->solo(12,o->value());} + xywh {295 175 15 15} selection_color 2 + code0 {solobutton[12]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button solo14 { + callback {control->solo(13,o->value());} + xywh {310 175 15 15} selection_color 2 + code0 {solobutton[13]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button solo15 { + callback {control->solo(14,o->value());} + xywh {325 175 15 15} selection_color 2 + code0 {solobutton[14]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button solo16 { + callback {control->solo(15,o->value());} + xywh {340 175 15 15} selection_color 2 + code0 {solobutton[15]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button solo17 { + callback {control->solo(16,o->value());} + xywh {430 175 15 15} selection_color 2 + code0 {solobutton[16]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button solo18 { + callback {control->solo(17,o->value());} + xywh {445 175 15 15} selection_color 2 + code0 {solobutton[17]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button solo19 { + callback {control->solo(18,o->value());} + xywh {460 175 15 15} selection_color 2 + code0 {solobutton[18]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button solo20 { + callback {control->solo(19,o->value());} + xywh {475 175 15 15} selection_color 2 + code0 {solobutton[19]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button solo21 { + callback {control->solo(20,o->value());} + xywh {490 175 15 15} selection_color 2 + code0 {solobutton[20]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button solo22 { + callback {control->solo(21,o->value());} + xywh {505 175 15 15} selection_color 2 + code0 {solobutton[21]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button solo23 { + callback {control->solo(22,o->value());} + xywh {520 175 15 15} selection_color 2 + code0 {solobutton[22]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button solo24 { + callback {control->solo(23,o->value());} + xywh {535 175 15 15} selection_color 2 + code0 {solobutton[23]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button mute1 { + callback {control->mute(0,o->value());} + xywh {40 192 20 15} selection_color 1 + code0 {o->up_image(button_mute_up->image()); o->down_image(button_mute_dn->image()); mutebutton[0]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button mute2 { + callback {control->mute(1,o->value());} + xywh {60 192 15 15} selection_color 1 + code0 {mutebutton[1]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button mute3 { + callback {control->mute(2,o->value());} + xywh {75 192 15 15} selection_color 1 + code0 {mutebutton[2]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button mute4 { + callback {control->mute(3,o->value());} + xywh {90 192 15 15} selection_color 1 + code0 {mutebutton[3]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button mute5 { + callback {control->mute(4,o->value());} + xywh {105 192 15 15} selection_color 1 + code0 {mutebutton[4]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button mute6 { + callback {control->mute(5,o->value());} + xywh {120 192 15 15} selection_color 1 + code0 {mutebutton[5]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button mute7 { + callback {control->mute(6,o->value());} + xywh {135 192 15 15} selection_color 1 + code0 {mutebutton[6]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button mute8 { + callback {control->mute(7,o->value());} + xywh {150 192 15 15} selection_color 1 + code0 {mutebutton[7]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button mute9 { + callback {control->mute(8,o->value());} + xywh {235 192 15 15} selection_color 1 + code0 {mutebutton[8]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button mute10 { + callback {control->mute(9,o->value());} + xywh {250 192 15 15} selection_color 1 + code0 {mutebutton[9]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button mute11 { + callback {control->mute(10,o->value());} + xywh {265 192 15 15} selection_color 1 + code0 {mutebutton[10]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button mute12 { + callback {control->mute(11,o->value());} + xywh {280 192 15 15} selection_color 1 + code0 {mutebutton[11]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button mute13 { + callback {control->mute(12,o->value());} + xywh {295 192 15 15} selection_color 1 + code0 {mutebutton[12]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button mute14 { + callback {control->mute(13,o->value());} + xywh {310 192 15 15} selection_color 1 + code0 {mutebutton[13]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button mute15 { + callback {control->mute(14,o->value());} + xywh {325 192 15 15} selection_color 1 + code0 {mutebutton[14]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button mute16 { + callback {control->mute(15,o->value());} + xywh {340 192 15 15} selection_color 1 + code0 {mutebutton[15]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button mute17 { + callback {control->mute(16,o->value());} + xywh {430 192 15 15} selection_color 1 + code0 {mutebutton[16]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button mute18 { + callback {control->mute(17,o->value());} + xywh {445 192 15 15} selection_color 1 + code0 {mutebutton[17]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button mute19 { + callback {control->mute(18,o->value());} + xywh {460 192 15 15} selection_color 1 + code0 {mutebutton[18]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button mute20 { + callback {control->mute(19,o->value());} + xywh {475 192 15 15} selection_color 1 + code0 {mutebutton[19]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button mute21 { + callback {control->mute(20,o->value());} + xywh {490 192 15 15} selection_color 1 + code0 {mutebutton[20]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button mute22 { + callback {control->mute(21,o->value());} + xywh {505 192 15 15} selection_color 1 + code0 {mutebutton[21]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button mute23 { + callback {control->mute(22,o->value());} + xywh {520 192 15 15} selection_color 1 + code0 {mutebutton[22]=o;} + class Fl_Image_Toggle_Button + } + Fl_Button mute24 { + callback {control->mute(23,o->value());} + xywh {535 192 15 15} selection_color 1 + code0 {mutebutton[23]=o;} + class Fl_Image_Toggle_Button + } + Fl_Box arm_unarm_all { + callback {hd24song* currsong=this->control->song(); +if (currsong==NULL) return; + +bool alltracksarmed=true; +for (unsigned int i=1;i<=currsong->logical_channels();i++) { + if (!currsong->trackarmed(i)) { + alltracksarmed=false; + break; + } +} +bool mustarm=false; +if (!alltracksarmed) { + mustarm=true; +} +for (unsigned int i=1;i<=currsong->logical_channels();i++) { + currsong->trackarmed(i,mustarm); +}} + tooltip {Arm tracks} xywh {10 156 10 10} box OVAL_BOX color 1 selection_color 1 + class Fl_Button + } + Fl_Box {} { + label S + tooltip Solo xywh {10 176 15 14} color 1 selection_color 1 labelfont 1 labelsize 12 + } + Fl_Box {} { + label M + tooltip Mute xywh {10 191 15 14} color 1 selection_color 1 labelfont 1 labelsize 12 + } + Fl_Group infodisplay {open + xywh {10 225 295 150} box DOWN_BOX color 0 + } { + Fl_Box ho1 { + image {images/7seg_8.gif} xywh {12 234 16 26} + code0 {o->image(i7seg0->image()); o->redraw();} + } + Fl_Box ho2 { + image {images/7seg_8.gif} xywh {27 234 16 26} + code0 {o->image(i7seg0->image()); o->redraw();} + } + Fl_Box mi1 { + image {images/7seg_8.gif} xywh {55 234 16 26} + code0 {o->image(i7seg0->image()); o->redraw();} + } + Fl_Box mi2 { + image {images/7seg_8.gif} xywh {70 234 16 26} + code0 {o->image(i7seg0->image()); o->redraw();} + } + Fl_Box se1 { + image {images/7seg_8.gif} xywh {98 234 16 26} + code0 {o->image(i7seg0->image()); o->redraw();} + } + Fl_Box se2 { + image {images/7seg_8.gif} xywh {113 234 16 26} + code0 {o->image(i7seg0->image()); o->redraw();} + } + Fl_Box fr1 { + image {images/7seg_8.gif} xywh {141 234 16 26} + code0 {o->image(i7seg0->image()); o->redraw();} + } + Fl_Box fr2 { + image {images/7seg_8.gif} xywh {156 234 16 26} + code0 {o->image(i7seg0->image()); o->redraw();} + } + Fl_Box {} { + label H + xywh {42 247 12 14} labelfont 3 labelsize 11 labelcolor 6 + } + Fl_Box {} { + label M + xywh {85 247 12 14} labelfont 3 labelsize 11 labelcolor 6 + } + Fl_Box {} { + label S + xywh {128 247 12 14} labelfont 3 labelsize 11 labelcolor 6 + } + Fl_Box {} { + label F + xywh {171 247 12 14} labelfont 3 labelsize 11 labelcolor 6 + } + Fl_Box l1c0 { + image {images/HD24_matrix_realsize.gif} xywh {13 274 20 26} + code0 {this->dispcell[0][0]=o;} + } + Fl_Box l1c1 { + image {images/HD24_matrix_realsize.gif} xywh {31 274 20 26} + code0 {this->dispcell[1][0]=o;} + } + Fl_Box l1c2 { + image {images/HD24_matrix_realsize.gif} xywh {49 274 20 26} + code0 {this->dispcell[2][0]=o;} + } + Fl_Box l1c3 { + image {images/HD24_matrix_realsize.gif} xywh {67 274 20 26} + code0 {this->dispcell[3][0]=o;} + } + Fl_Box l1c4 { + image {images/HD24_matrix_realsize.gif} xywh {85 274 20 26} + code0 {this->dispcell[4][0]=o;} + } + Fl_Box l1c5 { + image {images/HD24_matrix_realsize.gif} xywh {103 274 20 26} + code0 {this->dispcell[5][0]=o;} + } + Fl_Box l1c6 { + image {images/HD24_matrix_realsize.gif} xywh {121 274 20 26} + code0 {this->dispcell[6][0]=o;} + } + Fl_Box l1c7 { + image {images/HD24_matrix_realsize.gif} xywh {139 274 20 26} + code0 {this->dispcell[7][0]=o;} + } + Fl_Box l1c8 { + image {images/HD24_matrix_realsize.gif} xywh {157 274 20 26} + code0 {this->dispcell[8][0]=o;} + } + Fl_Box l1c9 { + image {images/HD24_matrix_realsize.gif} xywh {175 274 20 26} + code0 {this->dispcell[9][0]=o;} + } + Fl_Box l1ca { + image {images/HD24_matrix_realsize.gif} xywh {193 274 20 26} + code0 {this->dispcell[10][0]=o;} + } + Fl_Box l1cb { + image {images/HD24_matrix_realsize.gif} xywh {211 274 20 26} + code0 {this->dispcell[11][0]=o;} + } + Fl_Box l1cc { + image {images/HD24_matrix_realsize.gif} xywh {229 274 20 26} + code0 {this->dispcell[12][0]=o;} + } + Fl_Box l1cd { + image {images/HD24_matrix_realsize.gif} xywh {247 274 20 26} + code0 {this->dispcell[13][0]=o;} + } + Fl_Box l1ce { + image {images/HD24_matrix_realsize.gif} xywh {265 274 20 26} + code0 {this->dispcell[14][0]=o;} + } + Fl_Box l1cf { + image {images/HD24_matrix_realsize.gif} xywh {283 274 20 26} + code0 {this->dispcell[15][0]=o;} + } + Fl_Box l2c0 { + image {images/HD24_matrix_realsize.gif} xywh {12 304 20 26} + code0 {this->dispcell[0][1]=o;} + } + Fl_Box l2c1 { + image {images/HD24_matrix_realsize.gif} xywh {30 304 20 26} + code0 {this->dispcell[1][1]=o;} + } + Fl_Box l2c2 { + image {images/HD24_matrix_realsize.gif} xywh {48 304 20 26} + code0 {this->dispcell[2][1]=o;} + } + Fl_Box l2c3 { + image {images/HD24_matrix_realsize.gif} xywh {66 304 20 26} + code0 {this->dispcell[3][1]=o;} + } + Fl_Box l2c4 { + image {images/HD24_matrix_realsize.gif} xywh {84 304 20 26} + code0 {this->dispcell[4][1]=o;} + } + Fl_Box l2c5 { + image {images/HD24_matrix_realsize.gif} xywh {102 304 20 26} + code0 {this->dispcell[5][1]=o;} + } + Fl_Box l2c6 { + image {images/HD24_matrix_realsize.gif} xywh {120 304 20 26} + code0 {this->dispcell[6][1]=o;} + } + Fl_Box l2c7 { + image {images/HD24_matrix_realsize.gif} xywh {138 304 20 26} + code0 {this->dispcell[7][1]=o;} + } + Fl_Box l2c8 { + image {images/HD24_matrix_realsize.gif} xywh {156 304 20 26} + code0 {this->dispcell[8][1]=o;} + } + Fl_Box l2c9 { + image {images/HD24_matrix_realsize.gif} xywh {174 304 20 26} + code0 {this->dispcell[9][1]=o;} + } + Fl_Box l2ca { + image {images/HD24_matrix_realsize.gif} xywh {192 304 20 26} + code0 {this->dispcell[10][1]=o;} + } + Fl_Box l2cb { + image {images/HD24_matrix_realsize.gif} xywh {210 304 20 26} + code0 {this->dispcell[11][1]=o;} + } + Fl_Box l2cc { + image {images/HD24_matrix_realsize.gif} xywh {228 304 20 26} + code0 {this->dispcell[12][1]=o;} + } + Fl_Box l2cd { + image {images/HD24_matrix_realsize.gif} xywh {246 304 20 26} + code0 {this->dispcell[13][1]=o;} + } + Fl_Box l2ce { + image {images/HD24_matrix_realsize.gif} xywh {264 304 20 26} + code0 {this->dispcell[14][1]=o;} + } + Fl_Box l2cf { + image {images/HD24_matrix_realsize.gif} xywh {282 304 20 26} + code0 {this->dispcell[15][1]=o;} + } + Fl_Box autoanythingled { + label AUTO + xywh {193 233 65 8} box FLAT_BOX color 93 labelfont 1 labelsize 8 hide + } + Fl_Box autoplayled { + label PLAY + xywh {215 242 24 8} box FLAT_BOX color 93 labelfont 1 labelsize 8 hide + } + Fl_Box autortnled { + label RTN + xywh {240 242 18 8} box FLAT_BOX color 93 labelfont 1 labelsize 8 hide + } + Fl_Box autorecled { + label REC + xywh {193 242 21 8} box FLAT_BOX color 1 labelfont 1 labelsize 8 align 16 hide + } + Fl_Box rehearseled { + label REHEARSE + xywh {193 251 65 8} box FLAT_BOX color 1 labelfont 1 labelsize 8 + } + Fl_Box pitchled { + label PITCH + xywh {260 242 40 8} box FLAT_BOX color 6 labelfont 1 labelsize 8 hide + } + } + Fl_Button button_rehearse { + label REHEARSE + callback {control->button_rehearse_call();} + 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 + code0 {o->up_image(button_lrc_up->image()); o->down_image(button_lrc_dn->image());} + class Fl_Image_Toggle_Button + } + Fl_Button button_punchin { + label {PUNCH IN} + callback {control->handlelocatebutton(hd24song::LOCATEPOS_PUNCHIN);} + 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 + code0 {o->up_image(button_lrc_led_up->image()); o->down_image(button_lrc_led_dn->image());} + class Fl_Image_Button + } + Fl_Button button_punchout { + label {PUNCH OUT} + callback {control->handlelocatebutton(hd24song::LOCATEPOS_PUNCHOUT);} + 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 + code0 {o->up_image(button_lrc_led_up->image()); o->down_image(button_lrc_led_dn->image());} + class Fl_Image_Button + } + Fl_Button button_peakmode { + label {Peak +mode} + callback {this->currpeakmode=((this->currpeakmode)+1)%3; + +for (unsigned int i=0;itrackchan[i]->peakmode(this->currpeakmode); +} +switch (this->currpeakmode) +{ + case 0: // "No" "Peak Hold" + dispwrite(0," No " + " Peak Hold ",2000); + break; + case 1: // "Momentary" "Peak Hold" + dispwrite(0," Momentary " + " Peak Hold ",2000); + break; + case 2: // "Continuous" "Peak Hold" + dispwrite(0," Continuous " + " Peak Hold ",2000); + break; + default: + // ??????? + break; +}} + tooltip arm xywh {10 375 50 30} color 8 selection_color 8 labelfont 1 labelsize 10 labelcolor 7 + code0 {o->clear_visible_focus();} + class Fl_Button + } + Fl_Button button_peakclear { + label {Peak +clear} + callback {this->currpeakmode=((this->currpeakmode)+1)%3; + +for (unsigned int i=0;itrackchan[i]->peakreset(); +}} + tooltip arm xywh {60 375 50 30} color 8 selection_color 8 labelfont 1 labelsize 10 labelcolor 7 + code0 {o->clear_visible_focus();} + class Fl_Button + } + Fl_Button button_autoinput { + label {Auto +input} + callback {/* +if (currenthd24==NULL) return; +if (button_autoinput->value()==1) { + currenthd24->setautoinput(true); +} else { + currenthd24->setautoinput(false); +} +*/} + tooltip arm xywh {110 375 45 30} type Toggle color 8 selection_color 59 labelfont 1 labelsize 10 labelcolor 7 + code0 {o->clear_visible_focus();} + class Fl_Button + } + Fl_Button button_allinput { + label {All +input} + callback {/* +if (currenthd24==NULL) return; +if (button_allinput->value()==0) { + currenthd24->setallinput(false); +} else { + currenthd24->setallinput(true); +} +*/} + tooltip arm xywh {155 375 45 30} type Toggle color 8 selection_color 59 labelfont 1 labelsize 10 labelcolor 7 + code0 {o->clear_visible_focus();} + class Fl_Button + } + Fl_Choice stereoinmap { + label {Stereo input mapping} open + xywh {463 390 140 20} down_box BORDER_BOX labelsize 12 align 5 textsize 12 deactivate + } { + MenuItem {} { + label Normal + xywh {5 5 36 21} labelsize 12 + } + MenuItem {} { + label {Swap Left and Right} + xywh {15 15 36 21} labelsize 12 + } + MenuItem {} { + label {Mix to mono} + xywh {15 15 36 21} labelsize 12 + } + MenuItem {} { + label {Use Left only} + xywh {25 25 36 21} labelsize 12 + } + MenuItem {} { + label {Use Right only} + xywh {35 35 36 21} labelsize 12 + } + } + Fl_Roller {} { + label {Drag to Jog} + callback {// scrubwheel calls button_scrub_call()} + xywh {310 390 110 20} type Horizontal labelsize 12 align 1 minimum -1 step 2 + code0 {o->setui(this);} + class ScrubWheel + } + } + } + decl {/* === Audio/transport ===================================================== */} {} + decl {int hlbuttons_defaultcolor;} {public + } + Function {highlight_setbuttons(int value)} {open return_type void + } { + code {if (value==1) { + if (button_loopstart!=NULL) { + button_loopstart->up_image(button_lrc_led_on_up->image()); + button_loopstart->down_image(button_lrc_led_on_dn->image()); + } + if (button_loopend!=NULL) { + button_loopend->up_image(button_lrc_led_on_up->image()); + button_loopend->down_image(button_lrc_led_on_dn->image()); + } + if (button_punchin!=NULL) { + button_punchin->up_image(button_lrc_led_on_up->image()); + button_punchin->down_image(button_lrc_led_on_dn->image()); + } + if (button_punchout!=NULL) { + button_punchout->up_image(button_lrc_led_on_up->image()); + button_punchout->down_image(button_lrc_led_on_dn->image()); + } +} else { + button_loopstart->up_image(button_lrc_led_up->image()); + button_loopstart->down_image(button_lrc_led_dn->image()); + button_loopend->up_image(button_lrc_led_up->image()); + button_loopend->down_image(button_lrc_led_dn->image()); + button_punchin->up_image(button_lrc_led_up->image()); + button_punchin->down_image(button_lrc_led_dn->image()); + button_punchout->up_image(button_lrc_led_up->image()); + button_punchout->down_image(button_lrc_led_dn->image()); +} + if (button_punchout!=NULL) { button_punchout->redraw(); } + if (button_punchin!=NULL) { button_punchin->redraw(); } + if (button_loopstart!=NULL) { button_loopstart->redraw(); } + if (button_loopend!=NULL) { button_loopend->redraw();}} {} + } + Function {poll_callback(void* user)} {open return_type {static void} + } { + code {//HD24UserInterface* mythis=(HD24UserInterface*)user; +RecorderUI* mythis=(RecorderUI*)user; +int visible=0; + if (mythis->recordergroup->visible()) + { + visible=1; + } else { + visible=0; + } + + +if (mythis->control->ready()!=1) { return; } + +if (mythis->dispwritecountdown>0) +{ + mythis->dispwritecountdown--; + if (mythis->dispwritecountdown==0) { + mythis->disprestore(); + } +} + +if (mythis->busy!=1) { + mythis->busy=1; + mythis->blinkcounter=(mythis->blinkcounter+1)%BLINKRATE; + + if (visible==1) { + for (unsigned int i=0;itrackchan[i]->setval(mythis->control->data->trackpeak[i]); + } + + Fl_Image* oldimg; + Fl_Image* newimg=NULL; + + string* dur=NULL; + hd24song* mycurrsong=mythis->control->song(); + if (mycurrsong!=NULL) { + dur=mycurrsong->display_cursor(); + } else { + dur=new string("00:00:00.00"); + } + + + oldimg=mythis->ho1->image(); + mythis->ho1->image(mythis->i7seg[dur->c_str()[0]-'0']->image()); + if (newimg!=oldimg) mythis->ho1->redraw(); + + oldimg=mythis->ho2->image(); + mythis->ho2->image(mythis->i7seg[dur->c_str()[1]-'0']->image()); + if (newimg!=oldimg) mythis->ho2->redraw(); + + oldimg=mythis->mi1->image(); + mythis->mi1->image(mythis->i7seg[dur->c_str()[3]-'0']->image()); + if (newimg!=oldimg) mythis->mi1->redraw(); + + oldimg=mythis->mi2->image(); + mythis->mi2->image(mythis->i7seg[dur->c_str()[4]-'0']->image()); + if (newimg!=oldimg) mythis->mi2->redraw(); + + oldimg=mythis->se1->image(); + mythis->se1->image(mythis->i7seg[dur->c_str()[6]-'0']->image()); + if (newimg!=oldimg) mythis->se1->redraw(); + + oldimg=mythis->se2->image(); + mythis->se2->image(mythis->i7seg[dur->c_str()[7]-'0']->image()); + if (newimg!=oldimg) mythis->se2->redraw(); + oldimg=mythis->fr1->image(); + mythis->fr1->image(mythis->i7seg[dur->c_str()[9]-'0']->image()); + if (newimg!=oldimg) mythis->fr1->redraw(); + + oldimg=mythis->fr2->image(); + mythis->fr2->image(mythis->i7seg[dur->c_str()[10]-'0']->image()); + if (newimg!=oldimg) mythis->fr2->redraw(); + if ((mythis->mustdisplaytimer) && (mycurrsong !=NULL)) + { + + // mythis->setstatus(*dur); + __uint32 currloc=mycurrsong->cursorpos(); + if (mycurrsong->songlength_in_samples() >0) { + currloc=mycurrsong->cursorpos()/(mycurrsong->songlength_in_samples()/1000); + } else { + currloc=0; + } + if (mythis->slidermoved!=0) { + mythis->slidermoved--; + } else { + mythis->locationslider->value(currloc); + } + } + delete (dur); + } + +} +mythis->busy=0; +//Fl::add_timeout(TIMEOUT,poll_callback,user); + +AudioSystem* audio=mythis->control->audio; + +if (!audio->isinitialized()) return; +if (!audio->mustloop()) return; +audio->hd24_transport_locate((__sint64)(audio->looppos())); +audio->mustloop(false); +audio->looppos(0);} {} + } + Function {fl_check()} {open return_type void + } { + code {Fl::check();} {} + } + decl {int busy;} {public + } + decl {friend class ScrubWheel;} {} + decl {int uiredrawcount; /* to limit refreshing UI */} {public + } + Function {finish()} {open return_type void + } { + code {if (this==NULL) return; + +this->control->button_stop_call();} {} + } + Function {button_light(void* button,bool lit)} {open return_type void + } { + code {if (button==NULL) return; +if (((Fl_Image_Button*)button)==button_stop) +{ + if (lit==1) + { + button_stop->up_image(button_stop_uplit->image()); + button_stop->down_image(button_stop_dn->image()); + } + else + { + button_stop->up_image(button_stop_up->image()); + button_stop->down_image(button_stop_dn->image()); + } + button_stop->redraw(); + return; +}} {} + } + Function {button_up(void* button)} {open return_type void + } { + code {if (button==NULL) +{ + return; +} + +if ((void*)button==(void*)button_stop) +{ + button_stop->value(0); + button_stop->redraw(); + return; +} +if ((void*)button==(void*)button_play) +{ + button_play->value(0); + button_play->redraw(); + return; +} +if ((void*)button==(void*)button_rec) +{ + button_rec->value(0); + button_rec->redraw(); + return; +} +if ((void*)button==(void*)button_rew) +{ + button_rew->value(0); + button_rew->redraw(); + return; +} +if ((void*)button==(void*)button_ffwd) +{ + button_ffwd->value(0); + button_ffwd->redraw(); + return; +}} {} + } + Function {button_down(void* button)} {open return_type void + } { + code {if (button==NULL) +{ + return; +} + +if ((void*)button==(void*)button_stop) +{ + button_stop->value(1); + button_stop->redraw(); + return; +} +if ((void*)button==(void*)button_play) +{ + button_play->value(1); + button_play->redraw(); + return; +} +if ((void*)button==(void*)button_rec) +{ + button_rec->value(1); + button_rec->redraw(); + return; +} +if ((void*)button==(void*)button_rew) +{ + button_rew->value(1); + button_rew->redraw(); + return; +} +if ((void*)button==(void*)button_ffwd) +{ + button_ffwd->value(1); + button_ffwd->redraw(); + return; +}} {} + } +} 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 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "config.h" +#include "hd24fs.h" +#include "convertlib.h" + +#define VERSION "1.3 beta" +#define _LARGE_FILES +#define _FILE_OFFSET_BITS 64 +#define FILE_OFFSET_BITS 64 +#define LARGE_FILES +#define LARGEFILE64_SOURCE +#define SECTORSIZE 512 +#define ARGHEADER "--header=" + +#ifdef DARWIN +# define open64 open +# define lseek64 lseek +# define pread64 pread +# define creat64 creat +# define pwrite64 pwrite +#endif + +#ifndef WINDOWS +# include +#endif + +string device; +string headerfilename; +__uint64 writeoffset; +int force; +int expertmode; +int graphmode; +int enable_graphmode; +int disable_graphmode; + +// Check if a file exists +bool fileexists (string* fname) +{ + struct stat fi; + + if ((stat(fname->c_str(), &fi) != -1) && ((fi.st_mode & S_IFDIR) == 0)) { + return true; + } + + return false; +} + +// Check if file handle is invalid +bool isinvalidhandle(FSHANDLE handle) +{ +#ifdef WINDOWS + if (handle == FSHANDLE_INVALID) { + return true; + } +#else + if (handle == 0 || handle == FSHANDLE_INVALID) { + return true; + } +#endif + return false; +} + +// Output a message for expert only features +void expertmodemessage(string feature) +{ + cout << feature <<" is only allowed in expert mode." << endl; +} + +// Seek to a position in the drive +void hd24seek(FSHANDLE devhd24, __uint64 seekpos) +{ +#ifdef WINDOWS + LARGE_INTEGER li; + li.HighPart = seekpos >> 32; + li.LowPart = seekpos % ((__uint64) 1 << 32); + SetFilePointerEx(devhd24, li, NULL, FILE_BEGIN); +#else + lseek64(devhd24, seekpos, 0); +#endif + return; +} + +// Calculate a 32-bit checksum for a block +long unsigned int calcblockchecksum(hd24raw* rawdevice, unsigned long firstsector, unsigned long endsector) +{ + long unsigned int checksum32 = 0; + unsigned char origblock[5120]; + + for (unsigned long k = firstsector; k < endsector; k++) + { + rawdevice->readsectors(k, origblock, 1); + + for (unsigned long i = 0; i < SECTORSIZE; i += 4) + { + unsigned long num = Convert::getint32(origblock, i); + int byte1 = num % 256; + int byte2 = (num >> 8) % 256; + int byte3 = (num >> 16) % 256; + int byte4 = (num >> 24) % 256; + num = byte4 + (byte3 << 8) + (byte2 << 16) + (byte1 << 24); + checksum32 += num; + } + } + + return checksum32; +} + +// Write to a sector +long writesectors(FSHANDLE devhd24, unsigned long sectornum, unsigned char * buffer, int sectors) +{ + int WRITESIZE = SECTORSIZE * sectors; // allows searching across sector boundaries + hd24seek(devhd24, (__uint64) sectornum * 512); + +#ifdef WINDOWS + DWORD dummy; + long bytes = 0; + + if (WriteFile(devhd24, buffer, WRITESIZE, &dummy, NULL)) { + bytes = WRITESIZE; + }; +#else + long bytes = pwrite64(devhd24, buffer, WRITESIZE, (__uint64) sectornum * 512); +#endif + + return bytes; +} + +void writetofile(hd24raw* rawdevice,string filename, long firstsector,long endsector) +{ + int i; + unsigned char bootblock[5120]; +#if defined(LINUX) || defined(DARWIN) + FSHANDLE handle=creat64(filename.c_str(),O_WRONLY); +#endif +#ifdef WINDOWS + FSHANDLE handle=CreateFile(filename.c_str(),GENERIC_WRITE|GENERIC_READ, + FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); + if (isinvalidhandle(handle)) { + handle=CreateFile(filename.c_str(),GENERIC_WRITE|GENERIC_READ, + FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); + } + +#endif + if (isinvalidhandle(handle)) { + cout << "Cannot open file "<readsectors(i,bootblock,1); +#if defined(LINUX) || defined(DARWIN) + __uint64 targetoff=i; + targetoff-=firstsector; + targetoff+=writeoffset; + targetoff*=512; + ssize_t byteswritten=pwrite64(handle,bootblock,512,targetoff); +#endif +#ifdef WINDOWS + //DWORD dummy; + //long bytes=0; + __uint64 targetoff=i; + targetoff-=firstsector; + targetoff+=writeoffset; + __uint64 byteswritten=writesectors(handle,targetoff,bootblock,1); +#endif + if (byteswritten==0) { + cout << "Wrote 0 bytes to file. Access denied?" << endl; +#if defined(LINUX) || defined(DARWIN) + close (handle); +#endif +#ifdef WNDOWS + CloseHandle(handle); +#endif + return; + } + if ((i%1000)==0) { + string* x=Convert::int64tohex((__uint64)i*0x200); + cout << "Write offset " << *x << "\r"; + if (x!=NULL) { delete x; x=NULL; } + } + } +#if defined(LINUX) || defined(DARWIN) + close (handle); +#endif +#ifdef WINDOWS + CloseHandle(handle); +#endif + return; +} + +string getbinstr(string tofind) +{ + if (tofind.substr(0,1)=="'") { + // find literal string + tofind=tofind.substr(1,tofind.length()-2); + cout << "Find string " << tofind << endl; + } else { + string binstr=""; + string tmp=""; + tofind+=" "; + unsigned int i; + for (i=0;iL " << endl; + return 0; + } + + if ( + (editstr.substr(0,1)==" ") + ) + { + editstr=editstr.substr(1,editstr.length()-1); + + while ( + (editstr.substr(0,1)!=" ") + &&(editstr!="")) + { + strtopos+=editstr.substr(0,1); + editstr=editstr.substr(1,editstr.length()-1); + } + } else { + cout << "Syntax: mL " << endl; + return 0; + } + cout << " strfrompos=" << strfrompos << endl; + cout << " strmovelen=" << strmovelen << endl; + cout << " strtopos=" << strtopos << endl; + + long frompos=(Convert::hex2long(strfrompos)%SECTORSIZE); + long movelen=(Convert::hex2long(strmovelen)%SECTORSIZE); + long topos=(Convert::hex2long(strtopos)%SECTORSIZE); + cout << " pos=" << frompos << endl; + cout << " movelen=" << movelen << endl; + cout << " movepos=" << topos << endl; + void* x=malloc(movelen); + memcpy(x,bootblock+frompos,movelen); + memcpy(bootblock+topos,x,movelen); + free (x); + return 0; +} + +long editbytes(unsigned char* bootblock,string editstr) +{ + string strpos=""; + while ((editstr.substr(0,1)!=" ") &&(editstr!="")) { + strpos+=editstr.substr(0,1); + editstr=editstr.substr(1,editstr.length()-1); + } + if (editstr!="") { + editstr=editstr.substr(1,editstr.length()-1); + } + string binstr=getbinstr(editstr); + long pos=(Convert::hex2long(strpos)%SECTORSIZE); + cout << "binstr=" << binstr << " " << pos << endl; + memcpy(bootblock+pos,binstr.c_str(),binstr.length()); + return 0; +} + +void compareblock(hd24raw* rawdevice,unsigned long firstsector,unsigned long endsector,long current) +{ + unsigned int i; + unsigned int j; + unsigned int k; + unsigned char origblock[5120]; + unsigned char destblock[5120]; + string* startoff=Convert::int64tohex((__uint64)firstsector*512); + string* endoff=Convert::int64tohex((__uint64)endsector*512-1); + cout << "Compare range from offset "<< *startoff << " to offset " << *endoff <readsectors(k,origblock,1); + rawdevice->readsectors(k-firstsector+current,destblock,1); + for (i=0;ireadsectors(i,bootblock,2); + if ((i%0x1000)==0) { + string* curroff=Convert::int64tohex((__uint64)i*0x200); + cout << "Scan offset " << *curroff << "\r"; + delete curroff; curroff=NULL; + } + /* check if string found. */ + int j=0; + for (j=0;j<512;j++) { + + if (memcmp((const void *)&bootblock[j],(const void *)tofind.c_str(),(size_t)tofind.length())==0) { + string* foundoff=Convert::int64tohex((__uint64)i*512+j); + cout << endl << "Found on offset " << *foundoff << endl; + delete foundoff; foundoff=NULL; + return i; + } + } + } + cout << endl << "Not found." << endl; + return current; +} + +void fstfix(unsigned char * bootblock,int fixsize) +{ + for (int i=0;i no translate + if (!fsys->isOpen()) { + cout << "Cannot open hd24 device." << endl; + delete fsys; fsys=NULL; + if (rawdevice!=NULL) + { + delete rawdevice; + rawdevice=NULL; + } + return 1; + } + if (headerfilename!="") + { + if (!(fsys->useheaderfile(headerfilename))) + { + cout << "Couldn't load header file "<getdevicename() << endl; + /* Initialization */ + unsigned char bootblock[5120]; + unsigned long sectornum=0; + int nodump=0; + int noread=0; + int writesec=0; + unsigned long blockstart=0; + unsigned long blockend=0; + writeoffset=0; + unsigned long checksum=0; + string userinput; + string lastsearch=""; + if (expertmode==1) { + cout << "Expert mode enabled. " << endl; + cout << "Warning! Disk writes are enabled." << endl; + cout << "You now have the capability to destroy." << endl; + cout << "Proceed with extreme caution!" << endl; + } + +try{ + /* try block is intended to make sure hd24 device is closed on exit*/ + string filename="outfile.dmp"; + + do { + int i; + int j; + if (enable_graphmode==1) + { + cout << "Enabling graph mode." << endl; + graphmode=1; + enable_graphmode=0; + } + if (disable_graphmode==1) { + cout << "Disabling graph mode." << endl; + graphmode=0; + disable_graphmode=0; + } + if (writesec==1) { + rawdevice->writesectors(sectornum,bootblock,1); + writesec=0; + } + if (noread==0) { + rawdevice->readsectors(sectornum,bootblock,1); + } + noread=0; + long offset=sectornum*512; + if (nodump==0) { + cout << "Sector " << *Convert::int32tohex((long)sectornum) << endl; + + for (i=0;i0) + { + sectornum--; + } else { + sectornum=0; + } + continue; + } + if (userinput.substr(0,1)=="-") { + long sectoadd=Convert::hex2long(userinput.substr(1,userinput.length()-1)); + if ((__uint32)sectoadd>(__uint32)sectornum) + { + sectornum=0; + } else { + sectornum-=sectoadd; + } + continue; + } + if (userinput==".") { + noread=1; + continue; + } + if ((userinput.substr(0,1)=="?")||(userinput=="help")) { + cout << "Help for hd24hexview " << VERSION << endl; + cout << "==============================" << endl; + cout << "General:" < increment n sectors, then dump sector"< decrement n sectors, then dump sector"< dump sector " << endl; + cout << " d- dump sector totalnumberofsectors-" << endl; + cout << " d re-read current sector from disk" << endl; + cout << " ml " << endl; + cout << " move bytes from offset to " << endl; + cout << " o dump sector that contains offset " << endl; + cout << " s x y.. scan marked block for byte sequence x y ..." << endl; + cout << " s'...' scan marked block for exact string" << endl; + cout << " e

xx edit byte sequence at pos p to xxxx " << endl; + cout << " e

'x' edit pos p to string 'x'" << endl; + cout << endl; + cout << "Block commands:" << endl; + cout << " bb mark start of sector as block beginning" << endl; + cout << " be mark end of sector as block end" << endl; + cout << " bc block clear" << endl; + cout << " diff compare marked block with current" << endl; + cout << " p paste first sector of marked block to current sector" << endl; + cout << endl; + cout << "File commands:" << endl; + cout << " n set filename to xx" << endl; + cout << " n clear filename" << endl; + cout << " w write marked block to named file/device" << endl; + cout << " wo clear sector write offset for file/device write" << endl; + cout << " wo set write offset to xx sectors" << endl; + cout << " ws write back current edited sector to disk" << endl; + cout << "HD24 specific features:" << endl; + cout << " fix reverse byte ordering of 32 bit words" << endl; + cout << " for better human readability" << endl; + cout << " cs Calc checksum of selected block" << endl; + cout << " scs Set zero checksum of selected block" << endl; + + nodump=1; // inhibit viewing the sector after this command. + continue; + } + if (userinput.substr(0,2)=="bc") { + blockstart=0; + blockend=0; + cout << "Block selection cleared." << endl; + nodump=1; // inhibit viewing the sector after this command. + continue; + } + if (userinput.substr(0,2)=="bb") { + cout << "Block start set." << endl; + nodump=1; // inhibit viewing the sector after this command. + blockstart=sectornum; + continue; + } + if (userinput.substr(0,2)=="be") { + cout << "Block end set." << endl; + /* dump is startsector..endsector, + * excl. end sector. number of bytes to dump= + * (blockend-blockstart)*512 + */ + nodump=1; // inhibit viewing the sector after this command. + blockend=sectornum+1; + continue; + } + if (userinput.substr(0,2)=="cs") { + checksum=calcblockchecksum(rawdevice,blockstart,blockend); + cout << "Block checksum is " << checksum << endl; + nodump=1; + noread=1; + continue; + } + if (userinput.substr(0,3)=="scs") { + if (blockend-1!=sectornum) { + cout << "Current sector must be block end." << endl; + nodump=1; + noread=1; + continue; + } + unsigned long checksum=calcblockchecksum(rawdevice,blockstart,blockend); + unsigned long oldchecksum=0; + oldchecksum+=((unsigned char)(bootblock[511])); oldchecksum=oldchecksum <<8; + oldchecksum+=((unsigned char)(bootblock[510])); oldchecksum=oldchecksum <<8; + oldchecksum+=((unsigned char)(bootblock[509])); oldchecksum=oldchecksum <<8; + oldchecksum+=((unsigned char)(bootblock[508])); + oldchecksum-=checksum; + bootblock[508]=oldchecksum%256; oldchecksum=oldchecksum >> 8; + bootblock[509]=oldchecksum%256; oldchecksum=oldchecksum >> 8; + bootblock[510]=oldchecksum%256; oldchecksum=oldchecksum >> 8; + bootblock[511]=oldchecksum%256; oldchecksum=oldchecksum >> 8; + + noread=1; + continue; + } + if (userinput.substr(0,4)=="diff") { + nodump=1; // inhibit viewing the sector after this command. + if (blockend==blockstart) { + cout << "Please set block start/end first." << endl; + continue; + } + compareblock(rawdevice,blockstart,blockend,sectornum); + continue; + } + if (userinput.substr(0,1)=="s") { + if (userinput=="s") { + userinput+=lastsearch; + } else { + lastsearch=userinput.substr(1,userinput.length()-1); + } + if (blockend==blockstart) { + sectornum=scanforblock(rawdevice,lastsearch,0,0xffffffff,sectornum); + } else { + sectornum=scanforblock(rawdevice,lastsearch,blockstart,blockend,sectornum); + } + continue; + } + if (userinput=="version") { + cout << VERSION << endl; + nodump=1; // inhibit viewing the sector after this command. + noread=1; + continue; + } + if (userinput.substr(0,1)=="p") { + //paste + if (blockend==blockstart) { + nodump=1; + cout << "Mark a block first." << endl; + continue; + } + rawdevice->readsectors(blockstart,bootblock,1); + noread=1; + continue; + } + if (userinput.substr(0,1)=="e") { + string editstr=userinput.substr(1,userinput.length()-1); + editbytes(bootblock,editstr); + noread=1; + continue; + } + if (userinput.substr(0,1)=="m") { + string editstr=userinput.substr(1,userinput.length()-1); + movebytes(bootblock,editstr); + noread=1; + continue; + } + if (userinput=="d") { + continue; + } + + if (userinput.substr(0,2)=="d-") { + // if we have 10 sectors (0..9), last one is d-1=sector 9 + // so sector num is total number of secs - negnum + sectornum=rawdevice->getlastsectornum()-Convert::hex2long(userinput.substr(2,userinput.length()-2))+1; + continue; + } + + if (userinput.substr(0,1)=="d") { + sectornum=Convert::hex2long(userinput.substr(1,userinput.length()-1)); + continue; + } + if (userinput.substr(0,1)=="o") { + long offset=Convert::hex2long(userinput.substr(1,userinput.length()-1)); + offset-=(offset%512); + sectornum=offset/512; + } + if (userinput=="fix") { + fstfix(bootblock,512); + noread=1; + continue; + } + if (userinput.substr(0,1)=="n") { + int dangerousname=0; + if (userinput.substr(1,4)=="\\\\.\\") { + dangerousname=1; + } + if (userinput.substr(1,5)=="/dev/") { + dangerousname=1; + } + if (userinput.substr(1,4)=="//./") { + dangerousname=1; + } + if (dangerousname==1) { + if (expertmode==0) { + expertmodemessage("Writing to devices"); + } else { + filename=userinput.substr(1,userinput.length()-1); + cout << "OK, setting output file to device " << filename << endl; + cout << "Please take your time to make sure this is really the correct drive."<getnextfreesector(0xFFFFFFFF)) << endl; + cout << rawdevice->getnextfreesector(0xFFFFFFFF) << endl; + } + if (userinput=="commit") { + if (expertmode==1) { + cout << "Commit FS to disk." << endl; + fsys->commit(); + } + } + } while (userinput!="q"); + +} catch (string e) { + cout << "Exiting because of an unexpected error." << endl; + delete rawdevice; rawdevice=NULL; + delete fsys; fsys=NULL; + return 1; +} + delete rawdevice; rawdevice=NULL; + delete fsys; fsys=NULL; + return 0; +} + 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 @@ +#include +#include +#include +#include + +using namespace std; + +void showsongs(hd24project* currentproj) +{ + int numsongs = currentproj->songcount(); + + cout << "======================================================================" << endl; + + if (numsongs == 0) + { + cout << " There are no songs in this project." << endl; + } + + for (int i = 1; i <= numsongs; i++) + { + hd24song currsong = *(currentproj->getsong(i)); + string* songname1 = new string(""); + cout << " "; + + if (i < 10) + { + cout << " "; + } + + cout << i << ": "; + + string* currsname = currsong.songname(); + *songname1 += *currsname; + + cout << *(Convert::padright(*songname1, 20, " ")); + cout << *(currsong.display_duration()) << ", "; + + string* chans = Convert::int2str(currsong.logical_channels()); + chans = Convert::padleft(*chans,2," "); + + cout << *chans << "ch. " << currsong.samplerate() << " Hz "; + + delete(currsname); + delete(songname1); + + cout << endl; + } +} + +void showprojects(hd24fs* currenthd24) +{ + int numprojs = currenthd24->projectcount(); + + for (int i = 1; i <= numprojs; i++) + { + hd24project currproj = *(currenthd24->getproject(i)); + string* projname1 = new string(""); + string* currpname = currproj.projectname(); + *projname1 += *currpname; + + cout << "======================================================================" << endl << "Project " << i << ": "; + cout << *projname1 << endl; + + showsongs (&currproj); + + delete(currpname); + delete(projname1); + } +} + +int main() +{ + hd24fs* fsysp=new hd24fs((const char*)NULL); + hd24fs fsys=*fsysp; + string* volname; + + if (!fsys.isOpen()) + { + cout << "Cannot open hd24 device." << endl; + return 1; + } + + int devcount = fsys.hd24devicecount(); + + if (devcount > 1) + { + cout << "Number of hd24 devices found: " << fsys.hd24devicecount() << endl; + } + + for (int i = 0; i < devcount; i++) + { + hd24fs* currhd24 = new hd24fs((const char*)NULL,fsys.mode(), i); + + if (devcount > 1) + { + cout << "Showing info for device #" << i << endl; + } + + volname = currhd24->volumename(); + string vname = ""; + vname += *volname; + cout << "Volume name : " << vname<projectcount() << endl; + showprojects(currhd24); + delete currhd24; + } + + return 0; +} 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 @@ +//syx2bin.cpp +//converts an alesis hd24 .syx OS file to binary +using namespace std; +#include +#define SKIPCHARS 9 + +int main(int argc, char *argv[]) +{ + + FILE *pInfile; + FILE *pOutfile; + char *pInfilename, *pOutfilename; + int loop; + int msbits; + + if(argc < 3) + { + fprintf(stderr, "Usage : %s infile outfile\n",argv[0]); + exit(1); + } + + pInfilename = argv[1]; + pOutfilename = argv[2]; + + pInfile = fopen(pInfilename, "rb"); + if(!pInfile) + { + fprintf(stderr, "ERROR : couldn't open %s for reading\n", pInfilename); + exit(1); + } + pOutfile = fopen(pOutfilename, "wb"); + if(!pOutfile) + { + fprintf(stderr, "ERROR : couldn't open %s for writing\n", pOutfilename); + fclose(pInfile); //close open infile + exit(1); + } + + //skip F0 and 5 byte header + for(loop = 0; loop < SKIPCHARS; loop++) + { + fgetc(pInfile); + } + +// msbits = fgetc(pInfile); + unsigned char b[8]; + unsigned char header[64]; + int whichbyte=3; +int headerbyte=0; + unsigned int checksum=0; + int filesize=0; + int written=0; + while((msbits != EOF) && (msbits != 0xF7)) //get most significant bits byte + { + int i; + int j; + j=10; + + for (i=0;i<8;i++) { + b[i]=fgetc(pInfile); + if (b[i]==0xF7) { + msbits=0xF7; + j=i; + } + } + // convert 8->7 bytes + unsigned char bits=b[0]; + int max=8; + if (j>1); +#else + int onebit=(bits << 1) & 0x80; + b[i]|=onebit; + bits = (bits << 1); +#endif + fputc((unsigned char) b[i], pOutfile); + written++; + if (headerbyte<64) { + header[headerbyte]=b[i]; + headerbyte++; + } + else + { + if (filesize==0) { + int x1=(int)((unsigned char)header[47]); + int x2=(int)((unsigned char)header[46]); + int x3=(int)((unsigned char)header[45]); + int x4=(int)((unsigned char)header[44]); + filesize=x1+(256*x2)+(256*256*x3)+(256*256*256*x4); + } + } + whichbyte=(whichbyte+1)%4; + checksum=(checksum+b[i] ) % 256; +//((unsigned char)(b[i]) << (8*(whichbyte))) ; + if (filesize!=0) { + if (written>=filesize) break; + } + } + if (filesize!=0) { + if (written>=filesize) break; + } + + } + printf("Checksum=%x\n",checksum); + fclose(pInfile); + fclose(pOutfile); + return 0; +} + 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 @@ +#ifdef WINDOWS +namespace std {} +#endif +using namespace std; +#include +#include +#include "convertlib.h" +/* +** Copyright (C) 2001-2005 Erik de Castro Lopo +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU General Public License as published by +** the Free Software Foundation; either version 2 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU General Public License for more details. +** +** You should have received a copy of the GNU General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +#include + +/* Include this header file to use functions from libsndfile. */ +#include + +/* This will be the length of the buffer used to hold.frames while +** we process them. +*/ +#define BUFFER_LEN 1024 + +/* libsndfile can handle more than 6 channels but we'll restrict it to 6. */ +#define MAX_CHANNELS 6 +string inputfilename; +string outputfilename; +string format; +long rate; +long bits; +int convertfile(string inputfilename) { +/* This is a buffer of double precision floating point values + * which will hold our data while we process it. + */ + format="wav"; + cout << "Converting " << inputfilename << endl; + if (rate==0) { + if ( + (inputfilename.find("44k1",0) != string::npos) + ||(inputfilename.find("44K1",0) != string::npos) + ||(inputfilename.find("44100",0) != string::npos) + ) { + rate=44100; + } + if ( + (inputfilename.find("48k",0) != string::npos) + ||(inputfilename.find("48K",0) != string::npos) + ||(inputfilename.find("48000",0) != string::npos) + ) { + rate=48000; + } + if ( + (inputfilename.find("88k2",0) != string::npos) + ||(inputfilename.find("88K2",0) != string::npos) + ||(inputfilename.find("88200",0) != string::npos) + ) { + rate=88200; + } + if ( + (inputfilename.find("96k",0) != string::npos) + ||(inputfilename.find("96K",0) != string::npos) + ||(inputfilename.find("96000",0) != string::npos) + ) { + rate=96000; + } + } + bits=24; + static int data [BUFFER_LEN] ; + + /* A SNDFILE is very much like a FILE in the Standard C library. The + ** sf_open function return an SNDFILE* pointer when they sucessfully + ** open the specified file. + */ + SNDFILE *infile, *outfile ; + + /* A pointer to an SF_INFO stutct is passed to sf_open. + ** On read, the library fills this struct with information about the file. + ** On write, the struct must be filled in before calling sf_open. + */ + SF_INFO sfinfoin ; + SF_INFO sfinfoout; + int readcount ; + if (inputfilename=="") { + cout << "Must specify --input filename" << endl; + return 1; + } + if (outputfilename=="") { + outputfilename=inputfilename; + string ext=""; + if (format=="wav") { + ext=".wav"; + } + if (outputfilename.substr(outputfilename.length()-4,4)==".raw") { + outputfilename=outputfilename.substr(0,outputfilename.length()-4)+ext; + } + if (outputfilename=="") { + cout << "Must specify --output filename" << endl; + return 1; + } + } + const char *infilename = inputfilename.c_str(); + const char *outfilename = outputfilename.c_str(); + + /* Here's where we open the input file. We pass sf_open the file name and + ** a pointer to an SF_INFO struct. + ** On successful open, sf_open returns a SNDFILE* pointer which is used + ** for all subsequent operations on that file. + ** If an error occurs during sf_open, the function returns a NULL pointer. + ** + ** If you are trying to open a raw headerless file you will need to set the + ** format and channels fields of sfinfo before calling sf_open(). For + ** instance to open a raw 16 bit stereo PCM file you would need the following + ** two lines: + ** + ** sfinfo.format = SF_FORMAT_RAW | SF_FORMAT_PCM_16 ; + ** sfinfo.channels = 2 ; + */ + sfinfoin.format = SF_FORMAT_RAW | SF_FORMAT_PCM_24|SF_ENDIAN_BIG ; + sfinfoin.channels = 1 ; + + if (format=="wav") { + sfinfoout.format = SF_FORMAT_WAV ; + } + if (bits==16) { + sfinfoout.format|=SF_FORMAT_PCM_16; + } + if (bits==24) { + sfinfoout.format|=SF_FORMAT_PCM_24; + } + + sfinfoout.samplerate=rate; + sfinfoout.channels = 1 ; + if (! (infile = sf_open (infilename, SFM_READ, &sfinfoin))) + { /* Open failed so print an error message. */ + printf ("Not able to open input file %s.\n", infilename) ; + /* Print the error message from libsndfile. */ + puts (sf_strerror (NULL)) ; + return 1 ; + } ; + + /* Open the output file. */ + if (! (outfile = sf_open (outfilename, SFM_WRITE, &sfinfoout))) + { printf ("Not able to open output file %s.\n", outfilename) ; + puts (sf_strerror (NULL)) ; + return 1 ; + } ; + + /* While there are.frames in the input file, read them, process + ** them and write them to the output file. + */ + while ((readcount = sf_read_int (infile, data, BUFFER_LEN))) + { + sf_write_int (outfile, data, readcount) ; + } ; + + /* Close input and output files. */ + sf_close (infile) ; + sf_close (outfile) ; + return 0; +} + +int parsecommandline(int argc, char **argv) +{ + int invalid = 0; + + for (int c = 1; c < argc; c++) { + string arg = argv[c]; + + if (arg.substr(0, 1) != "-") { + inputfilename = arg; + outputfilename = ""; + convertfile(inputfilename); + continue; + } + + if (arg.substr(0,strlen("--input=")) == "--input=") { + inputfilename = arg.substr(strlen("--input=")); + continue; + } + + if (arg.substr(0,strlen("--output=")) == "--output=") { + outputfilename = arg.substr(strlen("--output=")); + continue; + } + + if (arg.substr(0,strlen("--rate=")) == "--rate=") { + rate = Convert::str2long(arg.substr(strlen("--rate="))); + continue; + } + + if (arg.substr(0,strlen("--bits=")) == "--bits=") { + bits = Convert::str2long(arg.substr(strlen("--bits="))); + continue; + } + + cout << "Invalid argument: " << arg << endl; + invalid = 1; + } + return invalid; +} + +int main (int argc, char **argv) +{ + rate = 0; + int invalid = parsecommandline(argc, argv); + + if (invalid!=0) { + return invalid; + } + + return 0 ; +} /* main */ + + +/* +** Do not edit or modify anything in this comment block. +** The arch-tag line is a file identity tag for the GNU Arch +** revision control system. +** +** arch-tag: de9fdd1e-b807-41ef-9d51-075ba383e536 +*/ 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 @@ +#include "config.h" +#include +#include +#include +#include +#include "hd24fs.h" +#include +#include +#include +#ifndef WINDOWS +#include +#endif +#include +#include +#include +#include "convertlib.h" +#define HEADERSIZE 44 +#define SAMPLES_IN_HALF_BUF 1024*1024 +#define SAMPLES_IN_FULL_BUF 2*SAMPLES_IN_HALF_BUF +#define BYTES_PER_SAM 3 +#define BYTES_IN_HALF_BUF BYTES_PER_SAM*SAMPLES_IN_HALF_BUF +#define BYTES_IN_FULL_BUF BYTES_PER_SAM*SAMPLES_IN_FULL_BUF +char audiobuf[BYTES_IN_FULL_BUF]; +char fixbuf[BYTES_IN_HALF_BUF]; +string inputfile; +string outputfile; +int simple=0; +FILE* infile; +FILE* outfile; +__uint64 writeoffset; + +void clearaudiobuf() +{ + int i; + for (i=0;i=(1<<23)) { + samval-=(1<<24); + } + return samval; +} +int topos(int samval) { + return samval+(1<<23); +} +bool fileexists (string* fname) { + struct stat fi; + if ((stat (fname->c_str(), &fi) != -1) && ((fi.st_mode & S_IFDIR) == 0)) { + return true; + } + return false; +} +void hd24seek(FSHANDLE devhd24,__uint64 seekpos) +{ +#if defined(LINUX) || defined(DARWIN) + lseek(devhd24,seekpos,0); +// lseek64(devhd24,seekpos,0); +#endif +#ifdef WINDOWS + LARGE_INTEGER li; + li.HighPart=seekpos>>32; + li.LowPart=seekpos%((__uint64)1<<32); + SetFilePointerEx(devhd24,li,NULL,FILE_BEGIN); +#endif + return; +} + +int parsecommandline(int argc, char ** argv) +{ + int invalid=0; + inputfile=""; + outputfile=""; + for (int c=1;c0) { + int writecount=fwrite((const void*)&buffer[0],1,HEADERSIZE,outfile); + if (writecount==0) { + cout << "Cannot write output file" << endl; + } + } + return; +} +void copyaudio(FILE* infile,FILE* outfile) { + int readcount; + do { + shiftaudiobuf(); + readcount=fread((void*)&audiobuf[BYTES_IN_HALF_BUF],1,BYTES_IN_HALF_BUF,infile); + for (int i=0; i0) { + int writecount=fwrite( + (void*)&audiobuf[BYTES_IN_HALF_BUF],1,readcount,outfile); + if (writecount==0) { + cout << "Cannot write output file" << endl; + } + } + + } + while (readcount>0); + return; +} +void simplecopyaudio(FILE* infile,FILE* outfile) +{ + int readcount; + do { + readcount=fread((void*)&audiobuf[BYTES_IN_HALF_BUF],1,BYTES_IN_HALF_BUF,infile); + for (int i=0; i0) { + int writecount=fwrite( + (void*)&audiobuf[BYTES_IN_HALF_BUF],1,readcount,outfile); + if (writecount==0) { + cout << "Cannot write output file" << endl; + } + } + + } + while (readcount>0); + return; +} +void dothefix(FILE* infile, FILE* outfile) +{ + copyheader(infile,outfile); + findmask(infile); + if (simple==1) { + simplecopyaudio(infile,outfile); + } else { + copyaudio(infile,outfile); + } +} +int main (int argc,char ** argv) +{ + int invalid=parsecommandline(argc,argv); + if (invalid!=0) { + return invalid; + } + if ((inputfile=="")||(outputfile=="")) { + cout << "Usage: hd24wavefix [--simple] --input= --output=" << endl; + return 1; + } + clearaudiobuf(); + // Open files + infile=fopen(inputfile.c_str(),"rb"); + outfile=fopen(outputfile.c_str(),"wb"); + dothefix(infile,outfile); + fclose(outfile); + fclose(infile); + return 0; +} 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 @@ +APPLnone + 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 @@ +APPLnone + 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 @@ +/* BIN2C Converts binary data to be included in C source codes */ + + +#include +#include +#include +#include + + +static void usage(void) +{ + fprintf(stderr, "BIN2C Binary to C converter\n"); + fprintf(stderr, "usage: BIN2C \n"); + exit(0); +} + + +int main(int argc, char **argv) +{ + FILE* binfile; + FILE* cfile; + struct stat statbuf; + long len; + int cntr; + unsigned char inbyte; + char varname[80], cfilename[80]; + + if (argc == 1) + usage(); + + if (! (binfile = fopen(argv[1], "rb"))) { + perror("fopen"); + exit(1); + } + + stat(argv[1], &statbuf); + len = statbuf.st_size; + + if (argc > 2) + strcpy(cfilename, argv[2]); + else + strcpy(cfilename,"bin2c.c"); + cfile = fopen(cfilename, "wt"); + + cntr = 0; + + if (argc > 3) + strcpy(varname, argv[3]); + else + strcpy(varname, "varname"); + + fprintf(cfile, "unsigned char %s[%ld] = {\n", varname, len); + + fread(&inbyte, 1, 1, binfile); + while (1) { + fprintf(cfile, "0X%02X", inbyte); + + fread(&inbyte, 1, 1, binfile); + if (feof(binfile)) + break; + fprintf(cfile, ","); + if (++cntr > 30) { + fprintf(cfile, "\n"); + cntr = 0; + } + } + + fprintf(cfile, "};\n"); + fclose(binfile); + fclose(cfile); + return 0; +} diff --git a/src/installer/hd24connect_icon.png b/src/installer/hd24connect_icon.png new file mode 100644 index 0000000..63bca94 Binary files /dev/null and b/src/installer/hd24connect_icon.png differ diff --git a/src/installer/icon.icns b/src/installer/icon.icns new file mode 100644 index 0000000..e1137cd Binary files /dev/null and b/src/installer/icon.icns 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 @@ + + + + + CFBundleIdentifier + com.hd24tools.hd24connect + CFBundleName + hd24connect + CFBundlePackageType + APPL + CFBundleVersion + 59 + CFBundleShortVersionString + HD24VERSION + CFBundleIconFile + icon.icns + CFBundleSignature + none + CFBundleExecutable + HD24connect + + + 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 @@ + + + + + CFBundleIdentifier + com.hd24tools.setup + CFBundleName + setup + CFBundlePackageType + APPL + CFBundleVersion + 59 + CFBundleShortVersionString + 0.6 + CFBundleIconFile + icon.icns + CFBundleSignature + none + CFBundleExecutable + HD24tools Setup + + + 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 @@ +// This is a very rudimentary installer framework- +// it won't do much more than copy a few files to the proper location. +// Of course there are a few wizard screens which are made in fluid (FLTK), +// these can be altered as needed. +// A small portion of the actual install stuff is done in the READY screen +// (search for it in the code), this could still be moved out to the +// installer_resources.h file. +// At this moment, desktop shortcuts are not yet created, for more info +// read +// http://delphi.about.com/od/windowsshellapi/a/create_lnk.htm (shell links) +#include +#include +#include +#include "ui_welcome.h" +#include "ui_license.h" +#include "ui_instdir.h" +#include "ui_ready.h" +#include "setupapi.cpp" +#include "installer_resources.h" +#include +#include +#include +#ifdef WINDOWS +#define DEFAULT_INSTDIR "C:\\HD24tools\\" +#include +#include +#define IDI_ICON1 101 +#endif +#ifndef WINDOWS +#define DEFAULT_INSTDIR "/usr/local/bin/HD24tools/" +#endif +#include +#include +#include +#ifndef WINDOWS +#include +#endif + +#define ALLOW_OVERWRITE true +#define NO_OVERWRITE false + +#ifndef S_IXGRP +#define S_IXGRP 0 +#endif +#ifndef S_IXOTH +#define S_IXOTH 0 +#endif +bool confirm(const char* question) +{ + int result=fl_choice(question,"No","Yes",NULL); + if (result==1) { + return true; + } +return false; +} + +int lastx=0; +int lasty=0; +string fullbinname=""; +int installer_writefile(unsigned char* filedata,long long filesize,const char* instdir,const char* filename,bool allow_overwrite) +{ + string fname=instdir; + fname+=filename; + fstream binfile(fname.c_str(),ios::binary|ios::out); + binfile.write(reinterpret_cast(filedata),filesize); + binfile.close(); +#ifndef WINDOWS + chmod(fname.c_str(),S_IRWXU|S_IXGRP|S_IRGRP|S_IXOTH|S_IROTH); +#endif + return 0; +} +void installer_getsysdir(char* sysdir) +{ + // on Windows: GetSystemDirectory() +} +void installer_getprogdir(char* progdir) +{ + // on Windows: getProgramDirectory() +} +int main(int argc, char **argv,char *envp[]) { + UI_Welcome ui_welcome; + UI_License ui_license; + UI_Instdir ui_instdir; + char* instdir=new char[4096]; + instdir[0]='\0'; + bool done=false; + char* currscreen; + currscreen=new char[9]; + currscreen="welcome"; +#ifndef WINDOWS + // on non-windows systems, default to user home dir + // (on non windows or no home found, + // defaults to systemwide dir) + int count=0; + char homedir[255]; + homedir[0]='\0'; + while (envp[count] != NULL) + { + if (strncmp(envp[count],"HOME=",5)==0) + { + strncpy(&homedir[0],&envp[count][5],250); + } + ++count; + } + + if (strlen(homedir)>0) + { + strncpy(&instdir[0],&homedir[0],128); + int dirlen=strlen(instdir)-1; + if ((instdir[dirlen]!='/') + &&(instdir[dirlen]!='\\')) + { +#ifdef WINDOWS + instdir[dirlen+1]='\\'; + instdir[dirlen+2]='\0'; +#else + instdir[dirlen+1]='/'; + instdir[dirlen+2]='\0'; +#endif + } + dirlen=strlen(instdir)-1; + strcat(instdir,"HD24tools/"); + } +#endif + int insterror=0; + int result=0; + UI_Ready ui_ready; + char* sysdir=new char[4096]; + installer_getsysdir(&sysdir[0]); + while (done==false) { + if (strncmp(currscreen,"done",4)==0) + { + done=true; + continue; + } + if (strncmp(currscreen,"welcome",7)==0) + { + Fl_Window *window = ui_welcome.make_window(&currscreen[0]); +#ifdef WINDOWS + window->icon((char *)LoadIcon(fl_display,MAKEINTRESOURCE(IDI_ICON1))); +#endif + window->position(lastx,lasty); + window->end(); + window->show(); //argc, argv); + Fl::run(); lastx=window->x(); lasty=window->y(); + + currscreen = ui_welcome.currscreen; + if (strncmp(currscreen,"next",4)==0) { + currscreen="license\0"; + continue; + } + if (strncmp(currscreen,"cancel",4)==0) { + currscreen="done\0"; + continue; + } + // screen closed otherwise + currscreen="done\0"; + continue; + } + if (strncmp(currscreen,"license",7)==0) + { + Fl_Window *window = ui_license.make_window(&currscreen[0]); +#ifdef WINDOWS + window->icon((char *)LoadIcon(fl_display,MAKEINTRESOURCE(IDI_ICON1))); +#endif + window->position(lastx,lasty); + window->end(); + window->show(); //argc, argv); + Fl::run(); lastx=window->x(); lasty=window->y(); + currscreen = ui_license.currscreen; + if (strncmp(currscreen,"back",4)==0) { + currscreen="welcome\0"; + continue; + } + if (strncmp(currscreen,"next",4)==0) { + currscreen="instdir\0"; + continue; + } + if (strncmp(currscreen,"cancel",4)==0) { + currscreen="done\0"; + continue; + } + // screen closed otherwise + currscreen="done\0"; + continue; + } + if (strncmp(currscreen,"instdir",7)==0) + { + if (instdir[0]=='\0') + { + strncpy(&instdir[0],DEFAULT_INSTDIR,128); + } + Fl_Window *window = ui_instdir.make_window(&currscreen[0],&instdir[0]); +#ifdef WINDOWS + window->icon((char *)LoadIcon(fl_display,MAKEINTRESOURCE(IDI_ICON1))); +#endif + window->position(lastx,lasty); + window->end(); + window->show(); //argc, argv); + Fl::run(); lastx=window->x(); lasty=window->y(); + currscreen = ui_instdir.currscreen; + instdir = ui_instdir.instdir; + int dirlen=strlen(instdir)-1; + if ((instdir[dirlen]!='/') + &&(instdir[dirlen]!='\\')) + { +#ifdef WINDOWS + instdir[dirlen+1]='\\'; + instdir[dirlen+2]='\0'; +#else + instdir[dirlen+1]='/'; + instdir[dirlen+2]='\0'; +#endif + } + if (strncmp(currscreen,"cancel",6)==0) { + currscreen="done\0"; + continue; + } + if (strncmp(currscreen,"back",4)==0) { + currscreen="license\0"; + continue; + } + if (!setupDirExists(instdir)) + { + bool mustcreate=confirm("Install directory does not exist. Create it?"); + if (!mustcreate) { + currscreen="instdir\0"; + continue; + } + setupCreateDir(instdir,0755); + + if (!(setupDirExists(instdir))) + { + fl_message("Could not create install directory.\nPlease create it manually, then try again."); + currscreen="instdir\0"; + continue; + } + } + if (strncmp(currscreen,"next",4)==0) { + currscreen="ready\0"; + continue; + } + // screen closed otherwise + currscreen="done\0"; + continue; + } + if (strncmp(currscreen,"ready",5)==0) + { + // READY + cout << "actually doing the install now" << endl; + insterror=0; + result=installer_writefile( + resource_hd24tools_manual,sizeof(resource_hd24tools_manual),(const char*)instdir,resource_hd24tools_manual_filename,ALLOW_OVERWRITE); + if (result!=0) { insterror=1; currscreen="done\0"; continue; } + result=installer_writefile( + resource_longliverec,sizeof(resource_longliverec),(const char*)instdir,resource_longliverec_filename,ALLOW_OVERWRITE); + if (result!=0) { insterror=1; currscreen="done\0"; continue; } + result=installer_writefile( + resource_unquickformat,sizeof(resource_unquickformat),instdir,resource_unquickformat_filename,ALLOW_OVERWRITE); + if (result!=0) { insterror=1; currscreen="done\0"; continue; } +#ifdef LINUX + /* for linux, wrap the binary into a shell script + * that prepends the application dir to the library + * search path */ + fullbinname=resource_hd24connect_filename; + fullbinname+="_bin"; + result=installer_writefile( + resource_hd24connect,sizeof(resource_hd24connect),(const char*)instdir,fullbinname.c_str(),ALLOW_OVERWRITE); + fullbinname=instdir; + fullbinname+=resource_hd24connect_filename; + fstream wrapper(fullbinname.c_str(),ios::out); + wrapper << "#!/bin/sh" << endl; + wrapper << "export LD_LIBRARY_PATH=" << instdir <<":$LD_LIBRARY_PATH" << endl; + wrapper << "exec " << instdir << "hd24connect_bin $*" << endl; + wrapper.close(); + chmod(fullbinname.c_str(),S_IRWXU|S_IXGRP|S_IRGRP|S_IXOTH|S_IROTH); +#endif +#ifdef WINDOWS + result=installer_writefile( + resource_hd24connect,sizeof(resource_hd24connect),(const char*)instdir,resource_hd24connect_filename,ALLOW_OVERWRITE); +#endif +#ifdef DARWIN + /* For MacOS, wrap the binary into a .app bundle. + * Note: What is called LD_LIBRARY_PATH under Linux + * is called DYLD_LIBRARY_PATH on MacOSX + */ + string bundledir=instdir; + bundledir+="hd24connect.app/"; + setupCreateDir(bundledir.c_str(),0755); + bundledir+="Contents/"; + setupCreateDir(bundledir.c_str(),0755); + string macosdir; + macosdir=bundledir+"MacOS/"; + setupCreateDir(macosdir.c_str(),0755); + string resourcedir=bundledir+"Resources/"; + setupCreateDir(resourcedir.c_str(),0755); + string strplist="Info.plist"; + string strpkginfo="PkgInfo"; + + result=installer_writefile(resource_plist_connect,sizeof(resource_plist_connect),bundledir.c_str(),"info.plist",ALLOW_OVERWRITE); + result=installer_writefile(resource_pkginfo_connect,sizeof(resource_pkginfo_connect),bundledir.c_str(),strpkginfo.c_str(),ALLOW_OVERWRITE); + result=installer_writefile(resource_hd24connect,sizeof(resource_hd24connect),macosdir.c_str(),resource_hd24connect_filename,ALLOW_OVERWRITE); + + +#endif + if (result!=0) { insterror=1; currscreen="done\0"; continue; } + result=installer_writefile( + resource_hd24hexview,sizeof(resource_hd24hexview),(const char*)instdir,resource_hd24hexview_filename,ALLOW_OVERWRITE); + if (result!=0) { insterror=1; currscreen="done\0"; continue; } + result=installer_writefile( + resource_libsndfile_1,sizeof(resource_libsndfile_1),(const char*)instdir,resource_libsndfile_1_filename,ALLOW_OVERWRITE); + if (result!=0) { insterror=1; currscreen="done\0"; continue; } +// result=installer_writefile( +// resource_portaudio,sizeof(resource_portaudio),(const char*)instdir,resource_portaudio_filename,NO_OVERWRITE); +// if (result!=0) { insterror=1; currscreen="done\0"; continue; } + + Fl_Window *window = ui_ready.make_window(&currscreen[0]); +#ifdef WINDOWS + window->icon((char *)LoadIcon(fl_display,MAKEINTRESOURCE(IDI_ICON1))); +#endif + window->position(lastx,lasty); + window->end(); + window->show(); //argc, argv); + Fl::run(); lastx=window->x(); lasty=window->y(); + + currscreen = ui_ready.currscreen; + if (strncmp(currscreen,"back",4)==0) { + currscreen="license\0"; + continue; + } + if (strncmp(currscreen,"next",4)==0) { + currscreen="doinst\0"; + continue; + } + if (strncmp(currscreen,"cancel",4)==0) { + currscreen="done\0"; + continue; + } + // screen closed otherwise + cout << "???" << currscreen << endl; + currscreen="done\0"; + continue; + } + if (strncmp(currscreen,"doinst",6)==0) + { + currscreen="done\0"; + continue; + } + cout << "Unknown screen '" << currscreen << "'." << endl; + done=true; + } + return 0; +} 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 @@ +/** BEGIN COPYRIGHT BLOCK + * Copyright (C) 2001 Sun Microsystems, Inc. Used by permission. + * Copyright (C) 2005 Red Hat, Inc. + * All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation version + * 2.1 of the License. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * END COPYRIGHT BLOCK **/ +#ifdef WINDOWS +#define XP_WIN32 +#endif +#ifndef MAX_PATH +#define MAX_PATH 127 +#endif +#ifndef TRUE +#define TRUE (1==1) +#endif +#ifndef FALSE +#define FALSE (1==0) +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef XP_WIN32 + #include + #include + #include + #include /* For _findfirst */ +#else + + + #include + #include + #include /* socket, bind */ + #include /* htonl */ + #include /* gethostbyname */ + #include /* inet_ntoa */ + #include + #include + +#endif + + +#define MINPORT 1024 +#define MAXPORT 65535 + + + + /********************************************************************* + ** + ** FUNCTION: setupIsDirEmpty + ** Replaced: IsDirEmpty + ** + ** DESCRIPTION: checks to see if directory empty + ** + ** + ** INPUTS: + ** + ** RETURN: + ** TRUE or FALSE + ** + ** SIDE EFFECTS: + ** none + ** RESTRICTIONS: + ** None + ** MEMORY: + **********************************************************************/ + +int setupIsDirEmpty(const char * pszPath) + { +#ifdef XP_WIN32 + int iReturn = TRUE; + char szFileSpec[MAX_PATH]; + WIN32_FIND_DATA fd; + HANDLE ff; + + if (!(pszPath)) + { + //setupLog(NULL, "setupIsDirEmpty failed: passed in NULL parameter for directory Name"); + return FALSE; + } + snprintf(szFileSpec, sizeof(szFileSpec), "%s\\*", pszPath); + if (!memchr(szFileSpec, 0, sizeof(szFileSpec))) return FALSE; /*overflow*/ + + ff = FindFirstFile(szFileSpec, &fd); + if (ff != INVALID_HANDLE_VALUE) + { + do + { + if (strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, "..")) + { + iReturn = FALSE; + break; + } + } while (FindNextFile(ff, &fd)); + FindClose(ff); + } + + return (iReturn); +#else + DIR *dirp; + struct dirent *dp; + bool rc = TRUE; + + dirp = opendir(pszPath); + while ((dp = readdir(dirp)) != NULL) + { + if (strcmp(dp->d_name, ".") && strcmp(dp->d_name, "..")) + { + rc = FALSE; + break; + } + } + closedir(dirp); + return rc; +#endif + + } + + /********************************************************************* + ** + ** FUNCTION: setupFileExist + ** Replaced: FileExist + ** + ** DESCRIPTION: returns 1 if file exists. + ** + ** INPUTS: + ** + ** RETURN: + ** TRUE or FALSE + ** + ** SIDE EFFECTS: + ** none + ** RESTRICTIONS: + ** None + ** MEMORY: + **********************************************************************/ +int setupFileExists(const char * pszFileName) + { + struct stat fi; + + if ((stat (pszFileName, &fi) != -1) && ((fi.st_mode & S_IFDIR) == 0)) + { + return TRUE; + } + else + { + return FALSE; + } + } + + + /********************************************************************* + ** + ** FUNCTION: setupDirExists + ** Replaced: DirExists + ** + ** DESCRIPTION: checks to see if directory exists + ** + ** + ** INPUTS: + ** + ** RETURN: + ** TRUE or FALSE + ** + ** SIDE EFFECTS: + ** none + ** RESTRICTIONS: + ** None + ** MEMORY: + **********************************************************************/ +int setupDirExists(const char * pszDirName) + { +#ifdef XP_WIN32 + unsigned int dwAttrs; + if (!(pszDirName)) + { + //setupLog(NULL, "DirExists failed: passed in NULL parameter for directory"); + return FALSE; + } + dwAttrs = GetFileAttributes(pszDirName); + if ((dwAttrs != 0xFFFFFFFF) && (dwAttrs & FILE_ATTRIBUTE_DIRECTORY)) + { + return TRUE; + } + return FALSE; +#else + struct stat fi; + + if (stat (pszDirName, &fi) == -1 || !S_ISDIR(fi.st_mode)) + { + return FALSE; + } + else + { + return TRUE; + } +#endif + } + + /********************************************************************* + ** + ** FUNCTION: setupCreateDir + ** Replaced: CreateDir + ** + ** DESCRIPTION: creates a directory + ** + ** + ** INPUTS: + ** + ** RETURN: + ** NT: TRUE or FALSE + ** UNIX: + ** 0 : OK + ** -1 : Can't create directory + ** -2 : input exists and is not a directory + ** -3 : Can't write to directory + ** + ** SIDE EFFECTS: + ** none + ** RESTRICTIONS: + ** None + ** MEMORY: + ** + **********************************************************************/ +bool setupCreateDir(const char * pszDirName, int mode) + { +#ifdef XP_WIN32 + char *pszDelim; + char szDirName[MAX_PATH]; + char szTmpDir[MAX_PATH] = ""; + int cbLen; + + if (!(pszDirName)) + { + //setupLog(NULL, "CreateDir failed: passed in NULL parameter for directory"); + return FALSE; + } + + if (strlen(pszDirName) >= sizeof(szDirName)) + { + //setupLog(NULL, "CreateDir failed: passed in too long directory"); + return FALSE; + } + + snprintf(szDirName, sizeof(szDirName), "%s", pszDirName); + if (!memchr(szDirName, 0, sizeof(szDirName))) return FALSE; /*overflow*/ + pszDelim = szDirName; + while ((pszDelim = strchr(pszDelim, '/')) != NULL) + { + *pszDelim = '\\'; + } + + pszDelim = szDirName; + while ((pszDelim = strchr(pszDelim, '\\')) != NULL) + { + cbLen = (pszDelim - szDirName); + strncpy(szTmpDir, szDirName, cbLen); + szTmpDir[cbLen] = '\0'; + CreateDirectory(szTmpDir, NULL); + pszDelim++; + } + + if (!CreateDirectory(szDirName, NULL)) + { +// char szLog[MAX_PATH+50]; + return FALSE; +// snprintf(szLog, sizeof(szLog), +// "setupCreateDir failed to create '%s'", pszDirName); +// if (!memchr(szLog, 0, sizeof(szLog))) return FALSE; /*overflow*/ + //setupLog(NULL, szLog); + } + return TRUE; +#else + struct stat fi; + char *s; + char *t; + + s = strdup(pszDirName); + t = s + 1; + + while (1) + { + t = strchr(t, '/'); + + if (t) + *t = '\0'; + if (stat(s, &fi) == -1) + { + if (mkdir(s, mode) == -1) + { + return FALSE; + } + } + else if (!S_ISDIR(fi.st_mode)) + { + return FALSE; + } + if (t) + *t++ = '/'; + else + break; + } + + if (access(pszDirName, W_OK) == -1) + { + return FALSE; + } + return TRUE; +#endif + } + /********************************************************************* + ** + ** FUNCTION: setupConvertsPathSlashes + ** Replaced: ConvertsPathSlashes + ** + ** DESCRIPTION: converts slashes TRUE UNIX to NT, FALSE NT to UNIX, + ** + ** INPUTS: + ** + ** RETURN: + ** TRUE or FALSE + ** + ** SIDE EFFECTS: + ** none + ** RESTRICTIONS: + ** None + ** MEMORY: + **********************************************************************/ +int setupConvertPathSlashes(const char * lpszPath, char * lpszNewPath, int bType ) + { + if (lpszPath == NULL) + return FALSE; + + /* create reverse slashes and escape them */ + while (*lpszPath) + { + if ((*lpszPath == '\\') || (*lpszPath == '/')) + { + if (bType) + *lpszNewPath = '\\'; + else + *lpszNewPath = '/'; + } + else + *lpszNewPath = *lpszPath; + lpszPath++; + lpszNewPath++; + } + return TRUE; + } + + +unsigned int setupExecProgram(const char *program, const char *where) +{ + char curdir[MAX_PATH]; + unsigned int ret; +#ifdef XP_WIN32 + char szWhere[MAX_PATH]; + char szProgram[MAX_PATH]; + STARTUPINFO si; + PROCESS_INFORMATION pi; + DWORD dwCreationFlags; +#endif + + if (!program) + { + //setupLogMessage("info", "setup", "setupExecProgram called with no program"); + return 0; + } + if (!setupFileExists(program)) + { + //setupLogMessage("info", "setup", "setupExecProgram called with invalid program %s", program); + } + getcwd(curdir, sizeof(curdir)); + + if (where) + { + chdir(where); + } +#ifndef XP_WIN32 + ret = system(program); +#else + snprintf(szProgram, sizeof(szProgram), "%s", program); + if (!memchr(szProgram, 0, sizeof(szProgram))) { + //setupLogMessage("info", "setup", "Too long program %s", program); + return 0; + } + snprintf(szWhere, sizeof(szWhere), "%s", where); + if (!memchr(szWhere, 0, sizeof(szWhere))) { + //setupLogMessage("info", "setup", "Too long arg %s", where); + return 0; + } + memset(&si,0,sizeof(si)); + si.cb = sizeof(si); + GetStartupInfo(&si); + si.wShowWindow = SW_SHOWDEFAULT; + dwCreationFlags = NORMAL_PRIORITY_CLASS | DETACHED_PROCESS; + ret = CreateProcess(NULL, szProgram, NULL, NULL, FALSE, dwCreationFlags, NULL, szWhere, &si, &pi); +#endif + + if (where) + { + chdir(curdir); + } + + return ret; +} + + +/********************************************************************* +** +** FUNCTION: setupGetDiskFreeSpace +** DESCRIPTION: get available disk space in Kilobyte +** +** INPUTS: Path name +** OUTPUTS: +** RETURN: available disk space in kilobyte +** SIDE EFFECTS: +** None +** RESTRICTIONS: +** None +** MEMORY: +********************************************************************** +*/ + +unsigned long setupGetDiskFreeSpace(const char *path) +{ +#ifdef XP_WIN32 + DWORD dwSectorsPerCluster; + DWORD dwBytesPerSector; + DWORD dwFreeClusters; + DWORD dwTotalClusters; + + if (GetDiskFreeSpace(path, &dwSectorsPerCluster, &dwBytesPerSector, &dwFreeClusters, &dwTotalClusters)) + { + long long clusterSize; + + clusterSize = dwSectorsPerCluster * dwBytesPerSector; + + return (unsigned long)((clusterSize / 1024.0) * dwFreeClusters); + } + + return 0; +#else + struct statvfs buf; + + statvfs(path, &buf); + + if (buf.f_frsize == 0) + return (unsigned long)(((unsigned long long)buf.f_bavail / 1024.0) * buf.f_bsize); + else + return (unsigned long)(((unsigned long long)buf.f_bavail / 1024.0) * buf.f_frsize); +#endif +} + 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 @@ +#!/bin/sh +# to start hd24connect on Mac +export HD24PATH=`echo $0|sed -e 's/starthd24connect\.command//'|sed -e 's/\/$//'` +export DYLD_LIBRARY_PATH=$HD24PATH/hd24connect.app/Contents/MacOS/:$DYLD_LIBRARY_PATH +open $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 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0107 +header_name {.h} +code_name {.cxx} +decl {using namespace std;} {public +} + +decl {\#include } {public +} + +class UI_Askpasswd {open +} { + decl {char* currscreen;} {public + } + decl {char* instdir;} {public + } + Function {make_window(char* p_currscreen,char* p_instdir)} {open + } { + Fl_Window {} { + label {HD24tools HD24VERSION - Setup Wizard} open selected + xywh {1246 284 590 350} type Double color 7 + code0 {currscreen=p_currscreen;} + code1 {instdir=p_instdir;} visible + } { + Fl_Box {} { + image {welcome.png} xywh {0 -137 165 487} + } + Fl_Button {} { + label {&Browse...} + xywh {505 191 80 20} color 53 labelsize 12 + } + Fl_Box {} { + label {Please enter your password} + xywh {175 -3 320 33} labelfont 1 labelsize 16 align 20 + } + Fl_Group {} {open + xywh {-5 315 620 35} box BORDER_BOX color 53 selection_color 47 + } { + Fl_Button button_next { + label {&Next >} + callback {currscreen="next\\0"; +Fl_Window* winx=Fl::first_window(); +winx->~Fl_Window();} + xywh {415 320 85 25} color 53 labelsize 12 + } + Fl_Button {} { + label Cancel + callback {currscreen="cancel\\0"; +Fl_Window* winx=Fl::first_window(); +winx->~Fl_Window();} + xywh {505 320 85 25} color 53 labelsize 12 + } + Fl_Button {} { + label {< &Back} + callback {currscreen="back\\0"; +Fl_Window* winx=Fl::first_window(); +winx->~Fl_Window();} + xywh {330 320 85 25} color 53 labelsize 12 + } + } + Fl_Output password { + xywh {175 191 325 20} labelsize 12 align 5 textsize 11 + } + Fl_Box {} { + label {The setup wizard needs administrator privileges to allow +writing to the folder where some HD24tools components +need to be installed. + +Please enter your password to allow the setup wizard +to access this folder. + +Alternatively, if you are an experienced user, you can +temporarily enable write access to the library directory.} + xywh {175 38 405 149} labelsize 12 align 21 + } + } + } +} 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 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0107 +header_name {.h} +code_name {.cxx} +decl {using namespace std;} {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +class UI_Instdir {open +} { + decl {char* currscreen;} {public + } + decl {char* instdir;} {public + } + Function {make_window(char* p_currscreen,char* p_instdir)} {open + } { + Fl_Window {} { + label {HD24tools HD24VERSION - Setup Wizard} open selected + xywh {1246 284 590 350} type Double color 7 + code0 {currscreen=p_currscreen;} + code1 {instdir=p_instdir;} visible + } { + Fl_Box {} { + image {welcome.png} xywh {0 -137 165 487} + } + Fl_Button {} { + label {&Browse...} + callback {Fl_Native_File_Chooser chooser; +chooser.title("Select installation directory"); +chooser.type(Fl_Native_File_Chooser::BROWSE_DIRECTORY||Fl_Native_File_Chooser::BROWSE_SAVE_DIRECTORY||Fl_Native_File_Chooser::NEW_FOLDER); +chooser.filter(""); + +string cdir=""; +cdir+=currdir->value(); + +chooser.directory(cdir.c_str()); +switch (chooser.show()) { + case -1: break; //error + case 1: break; //cancel + default: + if (chooser.filename()) { + currdir->value(chooser.filename()); + } + + break; +}} + xywh {505 125 80 20} color 53 labelsize 12 + } + Fl_Box {} { + label {Choose installation directory} + xywh {175 -3 320 33} labelfont 1 labelsize 16 align 20 + } + Fl_Group {} {open + xywh {-5 315 620 35} box BORDER_BOX color 53 selection_color 47 + } { + Fl_Button button_next { + label {&Next >} + callback {currscreen="next\\0"; +string newdir=currdir->value(); +strncpy(&instdir[0],newdir.c_str(),128); +Fl_Window* winx=Fl::first_window(); +winx->~Fl_Window();} + xywh {415 320 85 25} color 53 labelsize 12 + } + Fl_Button {} { + label Cancel + callback {currscreen="cancel\\0"; +Fl_Window* winx=Fl::first_window(); +winx->~Fl_Window();} + xywh {505 320 85 25} color 53 labelsize 12 + } + Fl_Button {} { + label {< &Back} + callback {currscreen="back\\0"; +Fl_Window* winx=Fl::first_window(); +winx->~Fl_Window();} + xywh {330 320 85 25} color 53 labelsize 12 + } + } + Fl_Input currdir { + xywh {175 125 325 20} labelsize 12 align 5 textsize 11 + code0 {currdir->value(p_instdir);} + } + Fl_Box {} { + label {Setup will install HD24tools in the following folder. To +install in a different folder, click Browse and select +another folder. + +After that, click Next to start the installation.} + xywh {175 38 370 81} labelsize 12 align 21 + } + } + } +} 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 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0107 +header_name {.h} +code_name {.cxx} +decl {using namespace std;} {public +} + +decl {\#include } {public +} + +class UI_License {open +} { + decl {char* currscreen;} {public + } + Function {make_window(char* p_currscreen)} {open + } { + Fl_Window {} { + label {HD24tools HD24VERSION - Setup Wizard} open selected + xywh {1302 140 590 350} type Double color 7 + code0 {currscreen=p_currscreen;} visible + } { + Fl_Box {} { + image {welcome.png} xywh {0 -137 165 487} + } + Fl_Box {} { + label {License Agreement} + xywh {175 -3 435 33} labelfont 1 labelsize 16 align 20 + } + Fl_Group agreedisagree {open + xywh {170 265 395 45} + } { + Fl_Round_Button agree { + label {I accept the terms in the license agreement} + callback {agree->value(1); +disagree->value(0); +button_next->activate();} + xywh {175 275 385 15} down_box ROUND_DOWN_BOX labelsize 12 + } + Fl_Round_Button disagree { + label {I do not accept the terms in the license agreement} + callback {agree->value(0); +disagree->value(1); +button_next->deactivate();} + xywh {175 290 385 20} down_box ROUND_DOWN_BOX value 1 labelsize 12 + } + } + Fl_Group {} {open + xywh {-5 315 620 35} box BORDER_BOX color 53 selection_color 47 + } { + Fl_Button button_next { + label {&Next >} + callback {currscreen="next\\0"; +Fl_Window* winx=Fl::first_window(); +winx->~Fl_Window();} + xywh {415 320 85 25} color 53 labelsize 12 + code0 {o->deactivate();} + } + Fl_Button {} { + label Cancel + callback {currscreen="cancel\\0"; +Fl_Window* winx=Fl::first_window(); +winx->~Fl_Window();} + xywh {505 320 85 25} color 53 labelsize 12 + } + Fl_Button {} { + label {< &Back} + callback {currscreen="back\\0"; +Fl_Window* winx=Fl::first_window(); +winx->~Fl_Window();} + xywh {330 320 85 25} color 53 labelsize 12 + } + } + Fl_Output {} { + label {Please read the following license agreement carefully.} + xywh {175 45 405 220} type Multiline labelsize 12 align 5 textsize 11 + 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.");} + } + } + } +} 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 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0107 +header_name {.h} +code_name {.cxx} +decl {using namespace std;} {public +} + +decl {\#include } {public +} + +class UI_Ready {open +} { + decl {char* currscreen;} {public + } + Function {make_window(char* p_currscreen)} {open + } { + Fl_Window {} { + label {HD24tools HD24VERSION - Setup Wizard} open + xywh {1302 140 590 350} type Double color 7 + code0 {currscreen=p_currscreen;} visible + } { + Fl_Box {} { + image {welcome.png} xywh {0 -137 165 487} + } + Fl_Box {} { + label {Installation Complete} + xywh {175 -3 435 33} labelfont 1 labelsize 16 align 20 + } + Fl_Group {} {open + xywh {-5 315 620 35} box BORDER_BOX color 53 selection_color 47 + } { + Fl_Button {} { + label Close + callback {currscreen="cancel\\0"; +Fl_Window* winx=Fl::first_window(); +winx->~Fl_Window();} + xywh {505 320 85 25} color 53 labelsize 12 + } + } + Fl_Box {} { + label {HD24tools installation has been completed successfully. +You may now run it from the installation path. + +Please click Close to terminate the installer.} selected + xywh {180 58 385 169} labelsize 12 align 21 + } + } + } +} 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 @@ +# data file for the Fltk User Interface Designer (fluid) +version 1.0107 +header_name {.h} +code_name {.cxx} +decl {using namespace std;} {public +} + +decl {\#include } {public +} + +class UI_Welcome {open +} { + decl {char* currscreen;} {public + } + Function {make_window(char* p_currscreen)} {open + } { + Fl_Window {} { + label {HD24tools HD24VERSION - Setup Wizard} open + xywh {308 186 590 350} type Double color 7 + code0 {currscreen=p_currscreen;} visible + } { + Fl_Box {} { + image {welcome.png} xywh {0 -137 165 487} + } + Fl_Box {} { + label {Welcome to the setup wizard for} + xywh {165 -3 440 33} labelfont 1 labelsize 16 + } + Fl_Box {} { + label {HD24tools version HD24VERSION} + xywh {165 22 440 31} labelfont 1 labelsize 16 + } + Fl_Group {} {open + xywh {-5 315 620 35} box BORDER_BOX color 53 selection_color 47 + } { + Fl_Button {} { + label {&Next >} + callback {currscreen="next\\0"; +Fl_Window* winx=Fl::first_window(); +winx->~Fl_Window();} + xywh {415 320 85 25} color 53 labelsize 12 + } + Fl_Button {} { + label Cancel + callback {currscreen="cancel\\0"; +Fl_Window* winx=Fl::first_window(); +winx->~Fl_Window();} + xywh {505 320 85 25} color 53 labelsize 12 + } + } + Fl_Box {} { + label {This Setup Wizard will install HD24tools version HD24VERSION +on your computer. + +Attention: You may need to run this wizard as administrator/ +superuser/root. + +Before continuing, please close all running programs. + + +WARNING: This program is protected by copyright law.} selected + xywh {185 77 390 173} labelsize 12 align 21 + } + } + } +} diff --git a/src/installer/welcome.png b/src/installer/welcome.png new file mode 100644 index 0000000..88b9a73 Binary files /dev/null and b/src/installer/welcome.png 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 @@ +#include +#include +#include +#include +#include +#include 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 @@ +#ifndef __FL_IMAGE_BUTTON_H +#define __FL_IMAGE_BUTTON_H +#include +#include + +class Fl_Image_Button: public Fl_Button { +private: + Fl_Image* upimage; + Fl_Image* downimage; +public: + Fl_Image* up_image(); + Fl_Image* down_image(); + void up_image(Fl_Image* p_up_image); + void down_image(Fl_Image* p_down_image); + void draw(); + Fl_Image_Button(int a,int b,int c,int d,const char* e); + Fl_Image_Button(int a,int b,int c,int d); +}; + +#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 @@ +#include +#include +#include +#ifndef NULL +#define NULL 0 +#endif +void Fl_Image_Button::up_image(Fl_Image* p_upimage) +{ + upimage=p_upimage; +} + +void Fl_Image_Button::down_image(Fl_Image* p_downimage) +{ + downimage=p_downimage; +} + +Fl_Image* Fl_Image_Button::up_image() +{ + return upimage; +} + +Fl_Image* Fl_Image_Button::down_image() +{ + return downimage; +} + +Fl_Image_Button::Fl_Image_Button(int a,int b,int c,int d,const char* e):Fl_Button(a,b,c,d,e) +{ + upimage=NULL; + downimage=NULL; + Fl_Button::clear_visible_focus(); +} +Fl_Image_Button::Fl_Image_Button(int a,int b,int c,int d):Fl_Button(a,b,c,d) +{ + upimage=NULL; + downimage=NULL; + Fl_Button::clear_visible_focus(); +} + +/*void Fl_Image_Button::draw() { + if (value()==0) + { + if (upimage!=NULL) { + this->image(upimage); + } + } else { + if (this->value()==1) + { + if (downimage!=NULL) { + this->image(downimage); + } + } + } + Fl_Button::draw(); +} + +*/ + + +void Fl_Image_Button::draw() +{ + // begin - Fl_Button::draw() (box section) + if (type() == FL_HIDDEN_BUTTON) return; + Fl_Color col = value() ? selection_color() : color(); + + + draw_box(value() ? (down_box()?down_box():fl_down(box())) : box(), col); + // end - Fl_Button::draw() (box section) + + // begin - modification to render up/down image + Fl_Boxtype box_; + Fl_Image* pic_; + + if(value()) + { + box_ = (down_box())? down_box() : fl_down(box()); + pic_ = downimage; + } + else + { + box_ = box(); + pic_ = upimage; + } + + if(pic_) + { + int xx = x() + Fl::box_dx(box_); + int yy = y() + Fl::box_dy(box_); + int ww = w() - Fl::box_dw(box_); + int hh = h() - Fl::box_dh(box_); + int xpos = (ww - pic_->w()) / 2; + int ypos = (hh - pic_->h()) / 2; + + fl_push_clip(xx, yy, ww, hh); + pic_->draw(xx + xpos, yy + ypos); + fl_pop_clip(); + } + // end- modification to render up/down image + + // begin - Fl_Button::draw() (label section) + if (labeltype() == FL_NORMAL_LABEL && value()) { + Fl_Color c = labelcolor(); + labelcolor(fl_contrast(c, col)); + draw_label(); + labelcolor(c); + } else draw_label(); + if (Fl::focus() == this) draw_focus(); + // end - Fl_Button::draw() (label section) +} + 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 @@ +#ifndef __FL_IMAGE_Repeat_Button_H +#define __FL_IMAGE_Repeat_Button_H +#include +#include + +class Fl_Image_Repeat_Button: public Fl_Repeat_Button { +private: + Fl_Image* upimage; + Fl_Image* downimage; +public: + Fl_Image* up_image(); + Fl_Image* down_image(); + void up_image(Fl_Image* p_up_image); + void down_image(Fl_Image* p_down_image); + void draw(); + Fl_Image_Repeat_Button(int a,int b,int c,int d,const char* e); + Fl_Image_Repeat_Button(int a,int b,int c,int d); +}; + +#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 @@ +#include +#include +#include + +#ifndef NULL +#define NULL 0 +#endif +void Fl_Image_Repeat_Button::up_image(Fl_Image* p_upimage) +{ + upimage=p_upimage; +} + +void Fl_Image_Repeat_Button::down_image(Fl_Image* p_downimage) +{ + downimage=p_downimage; +} + +Fl_Image* Fl_Image_Repeat_Button::up_image() +{ + return upimage; +} + +Fl_Image* Fl_Image_Repeat_Button::down_image() +{ + return downimage; +} + +Fl_Image_Repeat_Button::Fl_Image_Repeat_Button(int a,int b,int c,int d):Fl_Repeat_Button(a,b,c,d) +{ + upimage=NULL; + downimage=NULL; + Fl_Repeat_Button::clear_visible_focus(); +} + + +void Fl_Image_Repeat_Button::draw() +{ + // begin - Fl_Button::draw() (box section) + if (type() == FL_HIDDEN_BUTTON) return; + Fl_Color col = value() ? selection_color() : color(); + + + draw_box(value() ? (down_box()?down_box():fl_down(box())) : box(), col); + // end - Fl_Button::draw() (box section) + + // begin - modification to render up/down image + Fl_Boxtype box_; + Fl_Image* pic_; + + if(value()) + { + box_ = (down_box())? down_box() : fl_down(box()); + pic_ = downimage; + } + else + { + box_ = box(); + pic_ = upimage; + } + + if(pic_) + { + int xx = x() + Fl::box_dx(box_); + int yy = y() + Fl::box_dy(box_); + int ww = w() - Fl::box_dw(box_); + int hh = h() - Fl::box_dh(box_); + int xpos = (ww - pic_->w()) / 2; + int ypos = (hh - pic_->h()) / 2; + + fl_push_clip(xx, yy, ww, hh); + pic_->draw(xx + xpos, yy + ypos); + fl_pop_clip(); + } + // end- modification to render up/down image + + // begin - Fl_Button::draw() (label section) + if (labeltype() == FL_NORMAL_LABEL && value()) { + Fl_Color c = labelcolor(); + labelcolor(fl_contrast(c, col)); + draw_label(); + labelcolor(c); + } else draw_label(); + if (Fl::focus() == this) draw_focus(); + // end - Fl_Button::draw() (label section) +} + 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 @@ +#ifndef __FL_IMAGE_Toggle_Button_H +#define __FL_IMAGE_Toggle_Button_H +#include +#include + +class Fl_Image_Toggle_Button: public Fl_Toggle_Button { +private: + Fl_Image* upimage; + Fl_Image* downimage; +public: + Fl_Image* up_image(); + Fl_Image* down_image(); + void up_image(Fl_Image* p_up_image); + void down_image(Fl_Image* p_down_image); + void draw(); + Fl_Image_Toggle_Button(int a,int b,int c,int d,const char* e); + Fl_Image_Toggle_Button(int a,int b,int c,int d); +}; + +#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 @@ +#include +#include +#include +#ifndef NULL +#define NULL 0 +#endif +void Fl_Image_Toggle_Button::up_image(Fl_Image* p_upimage) +{ + upimage=p_upimage; +} + +void Fl_Image_Toggle_Button::down_image(Fl_Image* p_downimage) +{ + downimage=p_downimage; +} + +Fl_Image* Fl_Image_Toggle_Button::up_image() +{ + return upimage; +} + +Fl_Image* Fl_Image_Toggle_Button::down_image() +{ + return downimage; +} + +Fl_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) +{ + upimage=NULL; + downimage=NULL; + Fl_Toggle_Button::clear_visible_focus(); +} + +Fl_Image_Toggle_Button::Fl_Image_Toggle_Button(int a,int b,int c,int d):Fl_Toggle_Button(a,b,c,d) +{ + upimage=NULL; + downimage=NULL; + Fl_Toggle_Button::clear_visible_focus(); +} + + +void Fl_Image_Toggle_Button::draw() +{ + // begin - Fl_Button::draw() (box section) + if (type() == FL_HIDDEN_BUTTON) return; + Fl_Color col = value() ? selection_color() : color(); + + + draw_box(value() ? (down_box()?down_box():fl_down(box())) : box(), col); + // end - Fl_Button::draw() (box section) + + // begin - modification to render up/down image + Fl_Boxtype box_; + Fl_Image* pic_; + + if(value()) + { + box_ = (down_box())? down_box() : fl_down(box()); + pic_ = downimage; + } + else + { + box_ = box(); + pic_ = upimage; + } + + if(pic_) + { + int xx = x() + Fl::box_dx(box_); + int yy = y() + Fl::box_dy(box_); + int ww = w() - Fl::box_dw(box_); + int hh = h() - Fl::box_dh(box_); + int xpos = (ww - pic_->w()) / 2; + int ypos = (hh - pic_->h()) / 2; + + fl_push_clip(xx, yy, ww, hh); + pic_->draw(xx + xpos, yy + ypos); + fl_pop_clip(); + } + // end- modification to render up/down image + + // begin - Fl_Button::draw() (label section) + if (labeltype() == FL_NORMAL_LABEL && value()) { + Fl_Color c = Fl_Button::labelcolor(); + labelcolor(fl_contrast(c, col)); + draw_label(); + labelcolor(c); + } else draw_label(); + if (Fl::focus() == this) draw_focus(); + // end - Fl_Button::draw() (label section) +} + 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 @@ +// +// Fl_Native_File_Chooser.H -- FLTK native OS file chooser widget +// +// Copyright 2004 by Greg Ercolano. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// + +#ifndef FL_NATIVE_FILE_CHOOSER_H +#define FL_NATIVE_FILE_CHOOSER_H +#include +// Use Windows' chooser +#ifdef _WIN32 +#include +#endif + +// Use Apple's chooser +#ifdef __APPLE__ +#include +#endif + +// All else falls back to FLTK's own chooser +#if ! defined(__APPLE__) && !defined(_WIN32) +#include +#endif + +#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 @@ +// +// Fl_Native_File_Chooser.cxx -- FLTK native OS file chooser widget +// +// Copyright 2004 by Greg Ercolano. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Use Windows' chooser +#ifdef WINDOWS +#ifndef _WIN32 +#define _WIN32 +#endif +#endif +#ifdef DARWIN +#define __APPLE__ +#endif + +#ifdef _WIN32 +#include "Fl_Native_File_Chooser_WIN32.cxx" +#endif + +// Use Apple's chooser +#ifdef __APPLE__ +#include "Fl_Native_File_Chooser_MAC.cxx" +#endif + +// All else falls back to FLTK's own chooser +#if ! defined(__APPLE__) && !defined(_WIN32) +#include "Fl_Native_File_Chooser_FLTK.cxx" +#endif + 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 @@ +// +// Fl_Native_File_Chooser_DEFAULT.H -- FLTK native OS file chooser widget +// +// Copyright 2005 by Nathan Vander Wilt. +// March 2005 - wrapper around Fl_File_Chooser +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// + +// Use FLTK BROWSER +#include +#include + +class Fl_Native_File_Chooser { +public: + enum Type { + BROWSE_FILE = 0, + BROWSE_DIRECTORY, + BROWSE_MULTI_FILE, + BROWSE_MULTI_DIRECTORY, + BROWSE_SAVE_FILE, + BROWSE_SAVE_DIRECTORY + }; + enum Option { + NO_OPTIONS = 0x0000, // no options enabled + SAVEAS_CONFIRM = 0x0001, // Show native 'Save As' overwrite + // confirm dialog (if supported) + NEW_FOLDER = 0x0002, // Show 'New Folder' icon + // (if supported) + PREVIEW = 0x0004 // enable preview mode + }; +private: + int _btype; // kind-of browser to show() + int _options; // general options + char *_filter; // user supplied filter + char *_parsedfilt; // parsed filter + int _filtvalue; // selected filter + char *_preset_file; + char *_prevvalue; // Returned filename + char *_directory; + char *_errmsg; // error message + Fl_File_Chooser *file_chooser; + int _nfilters; + + // Private methods + void errmsg(const char *msg); + int type_fl_file(int); + void parse_filter(); + void keeplocation(); + +public: + Fl_Native_File_Chooser(int val=BROWSE_FILE); + ~Fl_Native_File_Chooser(); + + // Public methods + void type(int); + int type() const; + void options(int); + int options() const; + int count() const; + const char *filename() const; + const char *filename(int i) const; + void directory(const char *val); + const char *directory() const; + void title(const char *); + const char* title() const; + const char *filter() const; + void filter(const char *); + int filters() const { return(_nfilters); } + void filter_value(int i); + int filter_value() const; + void preset_file(const char*); + const char* preset_file() const; + const char *errmsg() const; + int show(); +}; 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 @@ +// +// Fl_Native_File_Chooser_DEFAULT.cxx -- FLTK native OS file chooser widget +// March 2005 - wrapper around Fl_File_Chooser by natevw +// +// Copyright 2005 by Nathan Vander Wilt. +// +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please keep code 80 column compliant. +// +// 10 20 30 40 50 60 70 +// | | | | | | | +// 4567890123456789012345678901234567890123456789012345678901234567890123456789 +// +#include +#include +#include +#include "common.cxx" + +static int G_init = 0; // 'first time' initialize flag + +// CTOR +Fl_Native_File_Chooser::Fl_Native_File_Chooser(int val) { + if ( G_init == 0 ) { + // Initialize when instanced for first time +// Fl_File_Icon::load_system_icons(); // OK to call more than once + G_init = 1; // eg. if app already called from main() + } + _btype = val; + _options = NO_OPTIONS; + _filter = NULL; + _parsedfilt = NULL; + _preset_file = NULL; + _prevvalue = NULL; + _directory = NULL; + _errmsg = NULL; + file_chooser = new Fl_File_Chooser(NULL, NULL, 0, NULL); + type(val); // do this after file_chooser created + _nfilters = 0; +} + +// DTOR +Fl_Native_File_Chooser::~Fl_Native_File_Chooser() { + delete file_chooser; + _filter = strfree(_filter); + _parsedfilt = strfree(_parsedfilt); + _preset_file = strfree(_preset_file); + _prevvalue = strfree(_prevvalue); + _directory = strfree(_directory); + _errmsg = strfree(_errmsg); +} + +// PRIVATE: SET ERROR MESSAGE +void Fl_Native_File_Chooser::errmsg(const char *msg) { + _errmsg = strfree(_errmsg); + _errmsg = strnew(msg); +} + +// PRIVATE: translate Native types to Fl_File_Chooser types +int Fl_Native_File_Chooser::type_fl_file(int val) { + switch (val) { + case BROWSE_FILE: + return(Fl_File_Chooser::SINGLE); + case BROWSE_DIRECTORY: + return(Fl_File_Chooser::SINGLE | Fl_File_Chooser::DIRECTORY); + case BROWSE_MULTI_FILE: + return(Fl_File_Chooser::MULTI); + case BROWSE_MULTI_DIRECTORY: + return(Fl_File_Chooser::DIRECTORY | Fl_File_Chooser::MULTI); + case BROWSE_SAVE_FILE: + return(Fl_File_Chooser::SINGLE | Fl_File_Chooser::CREATE); + case BROWSE_SAVE_DIRECTORY: + return(Fl_File_Chooser::DIRECTORY | Fl_File_Chooser::SINGLE | Fl_File_Chooser::CREATE); + default: + return(Fl_File_Chooser::SINGLE); + } +} + +void Fl_Native_File_Chooser::type(int val) { + _btype = val; + file_chooser->type(type_fl_file(val)); +} + +int Fl_Native_File_Chooser::type() const { + return(_btype); +} + +// SET OPTIONS +void Fl_Native_File_Chooser::options(int val) { + _options = val; +} + +// GET OPTIONS +int Fl_Native_File_Chooser::options() const { + return(_options); +} + +// Show chooser, blocks until done. +// RETURNS: +// 0 - user picked a file +// 1 - user cancelled +// -1 - failed; errmsg() has reason +// +int Fl_Native_File_Chooser::show() { + // FILTER + if ( _parsedfilt ) { + file_chooser->filter(_parsedfilt); + } + + // FILTER VALUE + // Set this /after/ setting the filter + // + if (_filtvalue!=-1) + { + file_chooser->filter_value(_filtvalue); + } + + // DIRECTORY + if ( _directory && _directory[0] ) { + file_chooser->directory(_directory); + } else { + file_chooser->directory(_prevvalue); + } + + // PRESET FILE + if ( _preset_file ) { + file_chooser->value(_preset_file); + } + + // OPTIONS: PREVIEW + file_chooser->preview( (options() & PREVIEW) ? 1 : 0); + + // OPTIONS: NEW FOLDER + if ( options() & NEW_FOLDER ) + file_chooser->type(file_chooser->type() | Fl_File_Chooser::CREATE); // on + + // SHOW + file_chooser->show(); + + while ( file_chooser->shown() ) { + Fl::wait(); // block while shown + } + + if ( file_chooser->value() && file_chooser->value()[0] ) { + _prevvalue = strfree(_prevvalue); + _prevvalue = strnew(file_chooser->value()); + _filtvalue = file_chooser->filter_value(); // update filter value + + // HANDLE SHOWING 'SaveAs' CONFIRM + if ( options() & SAVEAS_CONFIRM && type() == BROWSE_SAVE_FILE ) { + struct stat buf; + if ( stat(file_chooser->value(), &buf) != -1 ) { + if ( buf.st_mode & S_IFREG ) { // Regular file + exists? + if ( fl_choice("File exists. Are you sure you want to overwrite?", "Cancel", " OK ", NULL) == 0 ) { + return(1); + } + } + } + } + } + + if ( file_chooser->count() ) return(0); + else return(1); +} + +// RETURN ERROR MESSAGE +const char *Fl_Native_File_Chooser::errmsg() const { + return(_errmsg ? _errmsg : "No error"); +} + +// GET FILENAME +const char* Fl_Native_File_Chooser::filename() const { + if ( file_chooser->count() > 0 ) return(file_chooser->value()); + return(""); +} + +// GET FILENAME FROM LIST OF FILENAMES +const char* Fl_Native_File_Chooser::filename(int i) const { + if ( i < file_chooser->count() ) return(file_chooser->value(i+1)); // convert fltk 1 based to our 0 based + return(""); +} + +// SET TITLE +// Can be NULL if no title desired. +// +void Fl_Native_File_Chooser::title(const char *val) { + file_chooser->label(val); +} + +// GET TITLE +// Can return NULL if none set. +// +const char *Fl_Native_File_Chooser::title() const { + return(file_chooser->label()); +} + +// SET FILTER +// Can be NULL if no filter needed +// +void Fl_Native_File_Chooser::filter(const char *val) { + _filter = strfree(_filter); + _filter = strnew(val); + parse_filter(); +} + +// GET FILTER +const char *Fl_Native_File_Chooser::filter() const { + return(_filter); +} + +// SET SELECTED FILTER +void Fl_Native_File_Chooser::filter_value(int val) { + _filtvalue = val; +} + +// RETURN SELECTED FILTER +int Fl_Native_File_Chooser::filter_value() const { + return(_filtvalue); +} + +// GET TOTAL FILENAMES CHOSEN +int Fl_Native_File_Chooser::count() const { + return(file_chooser->count()); +} + +// PRESET PATHNAME +// Can be NULL if no preset is desired. +// +void Fl_Native_File_Chooser::directory(const char *val) { + _directory = strfree(_directory); + _directory = strnew(val); +} + +// GET PRESET PATHNAME +// Can return NULL if none set. +// +const char *Fl_Native_File_Chooser::directory() const { + return(_directory); +} + +// Convert our filter format to Fl_File_Chooser's format +// FROM TO (FLTK) +// ------------------------- -------------------------- +// "*.cxx" "*.cxx Files(*.cxx)" +// "C Files\t*.{cxx,h}" "C Files(*.{cxx,h})" +// "C Files\t*.{cxx,h}\nText Files\t*.txt" "C Files(*.{cxx,h})\tText Files(*.txt)" +// +// Returns a modified version of the filter that the caller is responsible +// for freeing with strfree(). +// +void Fl_Native_File_Chooser::parse_filter() { + _parsedfilt = strfree(_parsedfilt); // clear previous parsed filter (if any) + _nfilters = 0; + char *in = _filter; + if ( !in ) return; + + int has_name = strchr(in, '\t') ? 1 : 0; + + char mode = has_name ? 'n' : 'w'; // parse mode: n=title, w=wildcard + char wildcard[1024] = ""; // parsed wildcard + char name[1024] = ""; + + // Parse filter user specified + for ( ; 1; in++ ) { + + /*** DEBUG + printf("WORKING ON '%c': mode=<%c> name=<%s> wildcard=<%s>\n", + *in, mode, name, wildcard); + ***/ + + switch (*in) { + // FINISHED PARSING NAME? + case '\t': + if ( mode != 'n' ) goto regchar; + mode = 'w'; + break; + + // ESCAPE NEXT CHAR + case '\\': + ++in; + goto regchar; + + // FINISHED PARSING ONE OF POSSIBLY SEVERAL FILTERS? + case '\r': + case '\n': + case '\0': + // APPEND NEW FILTER TO LIST + if ( wildcard[0] ) { + // OUT: "name(wild)\tname(wild)" + char comp[2048]; + sprintf(comp, "%s%.511s(%.511s)", ((_parsedfilt)?"\t":""), name, wildcard); + _parsedfilt = strapp(_parsedfilt, comp); + _nfilters++; + //DEBUG printf("DEBUG: PARSED FILT NOW <%s>\n", _parsedfilt); + } + // RESET + wildcard[0] = name[0] = '\0'; + mode = strchr(in, '\t') ? 'n' : 'w'; + // DONE? + if ( *in == '\0' ) return; // done + else continue; // not done yet, more filters + + // Parse all other chars + default: // handle all non-special chars + regchar: // handle regular char + switch ( mode ) { + case 'n': chrcat(name, *in); continue; + case 'w': chrcat(wildcard, *in); continue; + } + break; + } + } + //NOTREACHED +} + +// SET PRESET FILENAME +void Fl_Native_File_Chooser::preset_file(const char* val) { + _preset_file = strfree(_preset_file); + _preset_file = strnew(val); +} + +// GET PRESET FILENAME +const char* Fl_Native_File_Chooser::preset_file() const { + return(_preset_file); +} 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 @@ +// +// Fl_Native_File_Chooser_MAC.H -- FLTK native OS file chooser widget +// +// Copyright 2004 by Greg Ercolano. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// 10 20 30 40 50 60 70 +// | | | | | | | +// 4567890123456789012345678901234567890123456789012345678901234567890123456789 + +// OSX-SPECIFIC NATIVE BROWSER +#ifdef __APPLE_CC__ +#include +#else +#include +#endif + +#include +#define MAXFILTERS 80 + +class Fl_Native_File_Chooser { +public: + enum Type { + BROWSE_FILE = 0, + BROWSE_DIRECTORY, + BROWSE_MULTI_FILE, + BROWSE_MULTI_DIRECTORY, + BROWSE_SAVE_FILE, + BROWSE_SAVE_DIRECTORY + }; + enum Option { + NO_OPTIONS = 0x0000, // no options enabled + SAVEAS_CONFIRM = 0x0001, // Show native 'Save As' overwrite + // confirm dialog (if supported) + NEW_FOLDER = 0x0002, // Show 'New Folder' icon + // (if supported) + PREVIEW = 0x0004, // enable preview mode + }; +protected: + NavDialogCreationOptions _opts; // file navigation options +private: + int _btype; // kind-of browser to show() + int _options; // general options + NavDialogRef _ref; // file navigation reference + NavActionState _keepstate; // holds button permissions + NavMenuItemSpec _tempitem; // Popup menu selection + char **_pathnames; // array of pathnames + int _tpathnames; // total pathnames + char *_directory; // default pathname to use + char *_title; // title for window + char *_preset_file; // the 'save as' filename + + char *_filter; // user-side search filter, eg: + // C Files\t*.[ch]\nText Files\t*.txt" + + char *_filt_names; // filter names (tab delimited) + // eg. "C Files\tText Files" + + char *_filt_patt[MAXFILTERS]; + // array of filter patterns, eg: + // _filt_patt[0]="*.{cxx,h}" + // _filt_patt[1]="*.txt" + + int _filt_total; // parse_filter() # of filters loaded + int _filt_value; // index of the selected filter + char *_errmsg; // error message + + // PRIVATE CLASS TO HANDLE NAVIGATION DIALOG REPLY STRUCT + // Class-ified, mainly to ensure proper cleanup. + // + class NavReply { + int _valid_reply; + NavReplyRecord _reply; + public: + NavReply(); + ~NavReply(); + int get_reply(NavDialogRef& ref); + int get_saveas_basename(char *s, int slen); + int get_dirname(char *s, int slen); + int get_pathnames(char **&pathnames, int& tpathnames); + }; + + // Private methods + void errmsg(const char *msg); + void clear_pathnames(); + void set_single_pathname(const char *s); + int get_saveas_basename(NavDialogRef& ref); + int get_pathnames(NavDialogRef& ref); + static void event_handler(NavEventCallbackMessage callBackSelector, + NavCBRecPtr cbparm, void *data); + + void clear_filters(); + void add_filter(const char *, const char *); + void parse_filter(const char *from); + static Boolean filter_proc_cb(AEDesc *, void *, void *, NavFilterModes); + Boolean filter_proc_cb2(AEDesc*, void*, void*, NavFilterModes); + int post(); + +public: + Fl_Native_File_Chooser(int val = BROWSE_FILE); + ~Fl_Native_File_Chooser(); + + // Public methods + void type(int); + int type() const; + void options(int); + int options() const; + int count() const; + const char *filename() const; + const char *filename(int i) const; + void directory(const char *); + const char *directory() const; + void title(const char *); + const char *title() const; + const char *filter() const; + void filter(const char *); + void filter_value(int i) { _filt_value = i; } + int filter_value() { return(_filt_value); } + int filters() { return(_filt_total); } + void preset_file(const char *); + const char *preset_file(); + const char *errmsg() const; + int show(); +}; 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 @@ +// +// Fl_Native_File_Chooser_MAC.cxx -- FLTK native OS file chooser widget +// +// Copyright 2004 by Greg Ercolano. +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please keep code 80 column compliant. +// +// 10 20 30 40 50 60 70 +// | | | | | | | +// 4567890123456789012345678901234567890123456789012345678901234567890123456789 +// +// TODO: +// o When doing 'open file', only dir is preset, not filename. +// Possibly 'preset_file' could be used to select the filename. +// +#include +#include +#include "common.cxx" // strnew/strfree/strapp/chrcat + +// TRY TO CONVERT AN AEDesc TO AN FSSpec +// As per Apple Technical Q&A QA1274 +// eg: http://developer.apple.com/qa/qa2001/qa1274.html +// Returns 'noErr' if OK, +// or an 'OSX result code' on error. +// +static int AEDescToFSSpec(const AEDesc* desc, FSSpec* fsspec) { + OSStatus err = noErr; + AEDesc coerceDesc; + // If AEDesc isn't already an FSSpec, convert it to one + if ( desc->descriptorType != typeFSS ) { + if ( ( err = AECoerceDesc(desc, typeFSS, &coerceDesc) ) == noErr ) { + // Get FSSpec out of AEDesc + err = AEGetDescData(&coerceDesc, fsspec, sizeof(FSSpec)); + AEDisposeDesc(&coerceDesc); + } + } else { + err = AEGetDescData(desc, fsspec, sizeof(FSSpec)); + } + return( err ); +} + +// CONVERT AN FSSpec TO A PATHNAME +static void FSSpecToPath(const FSSpec &spec, char *buff, int bufflen) { + FSRef fsRef; + FSpMakeFSRef(&spec, &fsRef); + FSRefMakePath(&fsRef, (UInt8*)buff, bufflen); +} + +// CONVERT REGULAR PATH -> FSSpec +// If file does not exist, expect fnfErr. +// Returns 'noErr' if OK, +// or an 'OSX result code' on error. +// +static OSStatus PathToFSSpec(const char *path, FSSpec &spec) { + OSStatus err; + FSRef ref; + if ((err = FSPathMakeRef((const UInt8*)path, &ref, NULL)) != noErr) { + return(err); + } + // FSRef -> FSSpec + if ((err = FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, &spec, + NULL)) != noErr) { + return(err); + } + return(noErr); +} + +// NAVREPLY: CTOR +Fl_Native_File_Chooser::NavReply::NavReply() { + _valid_reply = 0; +} + +// NAVREPLY: DTOR +Fl_Native_File_Chooser::NavReply::~NavReply() { + if ( _valid_reply ) { + NavDisposeReply(&_reply); + } +} + +// GET REPLY FROM THE NAV* DIALOG +int Fl_Native_File_Chooser::NavReply::get_reply(NavDialogRef& ref) { + if ( _valid_reply ) { + NavDisposeReply(&_reply); // dispose of previous + _valid_reply = 0; + } + if ( ref == NULL || NavDialogGetReply(ref, &_reply) != noErr ) { + return(-1); + } + _valid_reply = 1; + return(0); +} + +// RETURN THE BASENAME USER WANTS TO 'Save As' +int Fl_Native_File_Chooser::NavReply::get_saveas_basename(char *s, int slen) { + if (CFStringGetCString(_reply.saveFileName, s, slen-1, + kCFStringEncodingUTF8) == false) { + s[0] = '\0'; + return(-1); + } + return(0); +} + +// RETURN THE DIRECTORY NAME +// Returns 0 on success, -1 on error. +// +int Fl_Native_File_Chooser::NavReply::get_dirname(char *s, int slen) { + FSSpec fsspec; + if ( AEDescToFSSpec(&_reply.selection, &fsspec) != noErr ) { + // Conversion failed? Return empty name + s[0] = 0; + return(-1); + } + FSSpecToPath(fsspec, s, slen); + return(0); +} + +// RETURN MULTIPLE DIRECTORIES +// Returns: 0 on success with pathnames[] containing pathnames selected, +// -1 on error +// +int Fl_Native_File_Chooser::NavReply::get_pathnames(char **&pathnames, + int& tpathnames) { + // How many items selected? + long count = 0; + if ( AECountItems(&_reply.selection, &count) != noErr ) + { return(-1); } + + // Allocate space for that many pathnames + pathnames = new char*[count]; + memset((void*)pathnames, 0, count*sizeof(char*)); + tpathnames = count; + + // Walk list of pathnames selected + for (short index=1; index<=count; index++) { + AEKeyword keyWord; + AEDesc desc; + if (AEGetNthDesc(&_reply.selection, index, typeFSS, &keyWord, + &desc) != noErr) { + pathnames[index-1] = strnew(""); + continue; + } + FSSpec fsspec; + if (AEGetDescData(&desc, &fsspec, sizeof(FSSpec)) != noErr ) { + pathnames[index-1] = strnew(""); + continue; + } + char s[4096]; + FSSpecToPath(fsspec, s, sizeof(s)-1); + pathnames[index-1] = strnew(s); + AEDisposeDesc(&desc); + } + return(0); +} + +// FREE PATHNAMES ARRAY, IF IT HAS ANY CONTENTS +void Fl_Native_File_Chooser::clear_pathnames() { + if ( _pathnames ) { + while ( --_tpathnames >= 0 ) { + _pathnames[_tpathnames] = strfree(_pathnames[_tpathnames]); + } + delete [] _pathnames; + _pathnames = NULL; + } + _tpathnames = 0; +} + +// SET A SINGLE PATHNAME +void Fl_Native_File_Chooser::set_single_pathname(const char *s) { + clear_pathnames(); + _pathnames = new char*[1]; + _pathnames[0] = strnew(s); + _tpathnames = 1; +} + +// GET THE 'Save As' FILENAME +// Returns -1 on error, errmsg() has reason, filename == "". +// 0 if OK, filename() has filename chosen. +// +int Fl_Native_File_Chooser::get_saveas_basename(NavDialogRef& ref) { + if ( ref == NULL ) { + errmsg("get_saveas_basename: ref is NULL"); + return(-1); + } + NavReply reply; + OSStatus err; + if ((err = reply.get_reply(ref)) != noErr ) { + errmsg("NavReply::get_reply() failed"); + clear_pathnames(); + return(-1); + } + + char pathname[4096] = ""; + // Directory name.. + // -2 leaves room to append '/' + // + if ( reply.get_dirname(pathname, sizeof(pathname)-2) < 0 ) { + clear_pathnames(); + errmsg("NavReply::get_dirname() failed"); + return(-1); + } + // Append '/' + int len = strlen(pathname); + pathname[len++] = '/'; + pathname[len] = '\0'; + // Basename.. + if ( reply.get_saveas_basename(pathname+len, sizeof(pathname)-len) < 0 ) { + clear_pathnames(); + errmsg("NavReply::get_saveas_basename() failed"); + return(-1); + } + set_single_pathname(pathname); + return(0); +} + +// GET (POTENTIALLY) MULTIPLE FILENAMES +// Returns: +// -1 -- error, errmsg() has reason, filename == "" +// 0 -- OK, pathnames()/filename() has pathname(s) chosen +// +int Fl_Native_File_Chooser::get_pathnames(NavDialogRef& ref) { + if ( ref == NULL ) { + errmsg("get_saveas_basename: ref is NULL"); + return(-1); + } + NavReply reply; + OSStatus err; + if ((err = reply.get_reply(ref)) != noErr ) { + errmsg("NavReply::get_reply() failed"); + clear_pathnames(); + return(-1); + } + // First, clear pathnames array of any previous contents + clear_pathnames(); + if ( reply.get_pathnames(_pathnames, _tpathnames) < 0 ) { + clear_pathnames(); + errmsg("NavReply::get_dirname() failed"); + return(-1); + } + return(0); +} + +// NAV CALLBACK EVENT HANDLER +void Fl_Native_File_Chooser::event_handler( + NavEventCallbackMessage callBackSelector, + NavCBRecPtr cbparm, + void *data) { + OSStatus err; + Fl_Native_File_Chooser *nfb = (Fl_Native_File_Chooser*)data; + switch (callBackSelector) { + case kNavCBStart: + if ( nfb->directory() || nfb->preset_file() ) { + const char *pathname = nfb->directory() ? nfb->directory() : nfb->preset_file(); + FSSpec spec; + if ( ( err = PathToFSSpec(pathname, spec) ) != noErr ) { + fprintf(stderr, "PathToFSSpec(%s) failed: err=%d\n", + pathname, (int)err); + break; + } + AEDesc desc; + if ((err = AECreateDesc(typeFSS, + &spec, sizeof(FSSpec), &desc)) != noErr) { + fprintf(stderr, "AECreateDesc() failed: err=%d\n", + (int)err); + } + if ((err = NavCustomControl(cbparm->context, + kNavCtlSetLocation, &desc)) != noErr) { + fprintf(stderr, "NavCustomControl() failed: err=%d\n", + (int)err); + } + AEDisposeDesc(&desc); + } + if ( nfb->_btype == BROWSE_SAVE_FILE && nfb->preset_file() ) { + CFStringRef namestr = + CFStringCreateWithCString(NULL, + nfb->preset_file(), + kCFStringEncodingASCII); + NavDialogSetSaveFileName(cbparm->context, namestr); + CFRelease(namestr); + } + NavCustomControl(cbparm->context, kNavCtlSetActionState, + &nfb->_keepstate ); + + // Select the right filter in pop-up menu + if ( nfb->_filt_value == nfb->_filt_total ) { + // Select All Documents + NavPopupMenuItem kAll = kNavAllFiles; + NavCustomControl(cbparm->context, kNavCtlSelectAllType, &kAll); + } else if (nfb->_filt_value < nfb->_filt_total) { + // Select custom filter + nfb->_tempitem.version = kNavMenuItemSpecVersion; + nfb->_tempitem.menuCreator = 'extn'; + nfb->_tempitem.menuType = nfb->_filt_value; + *nfb->_tempitem.menuItemName = '\0'; // needed on 10.3+ + NavCustomControl(cbparm->context, + kNavCtlSelectCustomType, + &(nfb->_tempitem)); + } + break; + + case kNavCBPopupMenuSelect: + NavMenuItemSpecPtr ptr; + // they really buried this one! + ptr = (NavMenuItemSpecPtr)cbparm->eventData.eventDataParms.param; + if ( ptr->menuCreator ) { + // Gets index to filter ( menuCreator = 'extn' ) + nfb->_filt_value = ptr->menuType; + } else { + // All docs filter selected ( menuCreator = '\0\0\0\0' ) + nfb->_filt_value = nfb->_filt_total; + } + break; + + case kNavCBSelectEntry: + NavActionState astate; + switch ( nfb->_btype ) { + // these don't need selection override + case BROWSE_MULTI_FILE: + case BROWSE_MULTI_DIRECTORY: + case BROWSE_SAVE_FILE: + break; + + // These need to allow only one item, so disable + // Open button if user tries to select multiple files + case BROWSE_SAVE_DIRECTORY: + case BROWSE_DIRECTORY: + case BROWSE_FILE: + SInt32 selectcount; + AECountItems((AEDescList*)cbparm-> + eventData.eventDataParms.param, + &selectcount); + if ( selectcount > 1 ) { + NavCustomControl(cbparm->context, + kNavCtlSetSelection, + NULL); + astate = nfb->_keepstate | + kNavDontOpenState | + kNavDontChooseState; + NavCustomControl(cbparm->context, + kNavCtlSetActionState, + &astate ); + } + else { + astate= nfb->_keepstate | kNavNormalState; + NavCustomControl(cbparm->context, + kNavCtlSetActionState, + &astate ); + } + break; + } + break; + } +} + +// CONSTRUCTOR +Fl_Native_File_Chooser::Fl_Native_File_Chooser(int val) { + _btype = val; + NavGetDefaultDialogCreationOptions(&_opts); + _opts.optionFlags |= kNavDontConfirmReplacement; // no confirms for "save as" + _options = NO_OPTIONS; + _ref = NULL; + memset(&_tempitem, 0, sizeof(_tempitem)); + _pathnames = NULL; + _tpathnames = 0; + _title = NULL; + _filter = NULL; + _filt_names = NULL; + memset(_filt_patt, 0, sizeof(char*) * MAXFILTERS); + _filt_total = 0; + _filt_value = 0; + _directory = NULL; + _preset_file = NULL; + _errmsg = NULL; + _keepstate = kNavNormalState; +} + +// DESTRUCTOR +Fl_Native_File_Chooser::~Fl_Native_File_Chooser() { + // _opts // nothing to manage + if (_ref) { NavDialogDispose(_ref); _ref = NULL; } + // _options // nothing to manage + // _keepstate // nothing to manage + // _tempitem // nothing to manage + clear_pathnames(); + _directory = strfree(_directory); + _title = strfree(_title); + _preset_file = strfree(_preset_file); + _filter = strfree(_filter); + //_filt_names // managed by clear_filters() + //_filt_patt[i] // managed by clear_filters() + //_filt_total // managed by clear_filters() + clear_filters(); + //_filt_value // nothing to manage + _errmsg = strfree(_errmsg); +} + +// SET THE TYPE OF BROWSER +void Fl_Native_File_Chooser::type(int val) { + _btype = val; +} + +// GET TYPE OF BROWSER +int Fl_Native_File_Chooser::type() const { + return(_btype); +} + +// SET OPTIONS +void Fl_Native_File_Chooser::options(int val) { + _options = val; +} + +// GET OPTIONS +int Fl_Native_File_Chooser::options() const { + return(_options); +} + +// SHOW THE BROWSER WINDOW +// Returns: +// 0 - user picked a file +// 1 - user cancelled +// -1 - failed; errmsg() has reason +// +int Fl_Native_File_Chooser::show() { + // Make sure fltk interface updates before posting our dialog + Fl::flush(); + + // BROWSER TITLE + CFStringRef cfs_title; + cfs_title = CFStringCreateWithCString(NULL, + _title ? _title : "No Title", + kCFStringEncodingASCII); + _opts.windowTitle = cfs_title; + + _keepstate = kNavNormalState; + + // BROWSER FILTERS + CFArrayRef filter_array = NULL; + { + // One or more filters specified? + if ( _filt_total ) { + // NAMES -> CFArrayRef + CFStringRef tab = CFSTR("\t"); + CFStringRef tmp_cfs; + tmp_cfs = CFStringCreateWithCString(NULL, _filt_names, + kCFStringEncodingASCII); + filter_array = CFStringCreateArrayBySeparatingStrings( + NULL, tmp_cfs, tab); + CFRelease(tmp_cfs); + CFRelease(tab); + _opts.popupExtension = filter_array; + _opts.optionFlags |= kNavAllFilesInPopup; + } else { + filter_array = NULL; + _opts.popupExtension = NULL; + _opts.optionFlags |= kNavAllFilesInPopup; + } + } + + // HANDLE OPTIONS WE SUPPORT + if ( _options & SAVEAS_CONFIRM ) { + _opts.optionFlags &= ~kNavDontConfirmReplacement; // enables confirm + } else { + _opts.optionFlags |= kNavDontConfirmReplacement; // disables confirm + } + + // POST BROWSER + int err = post(); + + // RELEASE _FILT_ARR + if ( filter_array ) CFRelease(filter_array); + filter_array = NULL; + _opts.popupExtension = NULL; + _filt_total = 0; + + // RELEASE TITLE + if ( cfs_title ) CFRelease(cfs_title); + cfs_title = NULL; + + return(err); +} + +// POST BROWSER +// Internal use only. +// Assumes '_opts' has been initialized. +// +// Returns: +// 0 - user picked a file +// 1 - user cancelled +// -1 - failed; errmsg() has reason +// +int Fl_Native_File_Chooser::post() { + + // INITIALIZE BROWSER + OSStatus err; + if ( _filt_total == 0 ) { // Make sure they match + _filt_value = 0; // TBD: move to someplace more logical? + } + + if ( ! ( _options & NEW_FOLDER ) ) { + _keepstate |= kNavDontNewFolderState; + } + + switch (_btype) { + case BROWSE_FILE: + case BROWSE_MULTI_FILE: + // Prompt user for one or more files + if ((err = NavCreateGetFileDialog( + &_opts, // options + 0, // file types + event_handler, // event handler + 0, // preview callback + filter_proc_cb, // filter callback + (void*)this, // callback data + &_ref)) != noErr ) { // dialog ref + errmsg("NavCreateGetFileDialog: failed"); + return(-1); + } + break; + + case BROWSE_DIRECTORY: + case BROWSE_MULTI_DIRECTORY: + case BROWSE_SAVE_DIRECTORY: + // Prompts user for one or more files or folders + if ((err = NavCreateChooseFolderDialog( + &_opts, // options + event_handler, // event callback + 0, // filter callback + (void*)this, // callback data + &_ref)) != noErr ) { // dialog ref + errmsg("NavCreateChooseFolderDialog: failed"); + return(-1); + } + break; + + case BROWSE_SAVE_FILE: + // Prompt user for filename to 'save as' + if ((err = NavCreatePutFileDialog( + &_opts, // options + 0, // file types + 0, // file creator + event_handler, // event handler + (void*)this, // callback data + &_ref)) != noErr ) { // dialog ref + errmsg("NavCreatePutFileDialog: failed"); + return(-1); + } + break; + } + + // SHOW THE DIALOG + if ( ( err = NavDialogRun(_ref) ) != 0 ) { + char msg[80]; + sprintf(msg, "NavDialogRun: failed (err=%d)", (int)err); + errmsg(msg); + return(-1); + } + + // WHAT ACTION DID USER CHOOSE? + NavUserAction act = NavDialogGetUserAction(_ref); + if ( act == kNavUserActionNone ) { + errmsg("Nothing happened yet (dialog still open)"); + return(-1); + } + else if ( act == kNavUserActionCancel ) { // user chose 'cancel' + return(1); + } + else if ( act == kNavUserActionSaveAs ) { // user chose 'save as' + return(get_saveas_basename(_ref)); + } + + // TOO MANY FILES CHOSEN? + int ret = get_pathnames(_ref); + if ( _btype == BROWSE_FILE && ret == 0 && _tpathnames != 1 ) { + char msg[80]; + sprintf(msg, "Expected only one file to be chosen.. you chose %d.", + (int)_tpathnames); + errmsg(msg); + return(-1); + } + return(err); +} + +// SET ERROR MESSAGE +// Internal use only. +// +void Fl_Native_File_Chooser::errmsg(const char *msg) { + _errmsg = strfree(_errmsg); + _errmsg = strnew(msg); +} + +// RETURN ERROR MESSAGE +const char *Fl_Native_File_Chooser::errmsg() const { + return(_errmsg ? _errmsg : "No error"); +} + +// GET FILENAME +const char* Fl_Native_File_Chooser::filename() const { + if ( _pathnames && _tpathnames > 0 ) return(_pathnames[0]); + return(""); +} + +// GET FILENAME FROM LIST OF FILENAMES +const char* Fl_Native_File_Chooser::filename(int i) const { + if ( _pathnames && i < _tpathnames ) return(_pathnames[i]); + return(""); +} + +// GET TOTAL FILENAMES CHOSEN +int Fl_Native_File_Chooser::count() const { + return(_tpathnames); +} + +// PRESET PATHNAME +// Value can be NULL for none. +// +void Fl_Native_File_Chooser::directory(const char *val) { + _directory = strfree(_directory); + _directory = strnew(val); +} + +// GET PRESET PATHNAME +// Returned value can be NULL if none set. +// +const char* Fl_Native_File_Chooser::directory() const { + return(_directory); +} + +// SET TITLE +// Value can be NULL if no title desired. +// +void Fl_Native_File_Chooser::title(const char *val) { + _title = strfree(_title); + _title = strnew(val); +} + +// GET TITLE +// Returned value can be NULL if none set. +// +const char *Fl_Native_File_Chooser::title() const { + return(_title); +} + +// SET FILTER +// Can be NULL if no filter needed +// +void Fl_Native_File_Chooser::filter(const char *val) { + _filter = strfree(_filter); + _filter = strnew(val); + + // Parse filter user specified + // IN: _filter = "C Files\t*.{cxx,h}\nText Files\t*.txt" + // OUT: _filt_names = "C Files\tText Files" + // _filt_patt[0] = "*.{cxx,h}" + // _filt_patt[1] = "*.txt" + // _filt_total = 2 + // + parse_filter(_filter); +} + +// GET FILTER +// Returned value can be NULL if none set. +// +const char *Fl_Native_File_Chooser::filter() const { + return(_filter); +} + +// CLEAR ALL FILTERS +// Internal use only. +// +void Fl_Native_File_Chooser::clear_filters() { + _filt_names = strfree(_filt_names); + for (int i=0; i<_filt_total; i++) { + _filt_patt[i] = strfree(_filt_patt[i]); + } + _filt_total = 0; +} + +// PARSE USER'S FILTER SPEC +// Parses user specified filter ('in'), +// breaks out into _filt_patt[], _filt_names, and _filt_total. +// +// Handles: +// IN: OUT:_filt_names OUT: _filt_patt +// ------------------------------------ ------------------ --------------- +// "*.{ma,mb}" "*.{ma,mb} Files" "*.{ma,mb}" +// "*.[abc]" "*.[abc] Files" "*.[abc]" +// "*.txt" "*.txt Files" "*.c" +// "C Files\t*.[ch]" "C Files" "*.[ch]" +// "C Files\t*.[ch]\nText Files\t*.cxx" "C Files" "*.[ch]" +// +// Parsing Mode: +// IN:"C Files\t*.{cxx,h}" +// ||||||| ||||||||| +// mode: nnnnnnn wwwwwwwww +// \_____/ \_______/ +// Name Wildcard +// +void Fl_Native_File_Chooser::parse_filter(const char *in) { + clear_filters(); + if ( ! in ) return; + int has_name = strchr(in, '\t') ? 1 : 0; + + char mode = has_name ? 'n' : 'w'; // parse mode: n=title, w=wildcard + char wildcard[1024] = ""; // parsed wildcard + char name[1024] = ""; + + // Parse filter user specified + for ( ; 1; in++ ) { + + //// DEBUG + //// printf("WORKING ON '%c': mode=<%c> name=<%s> wildcard=<%s>\n", + //// *in, mode, name, wildcard); + + switch (*in) { + // FINISHED PARSING NAME? + case '\t': + if ( mode != 'n' ) goto regchar; + mode = 'w'; + break; + + // ESCAPE NEXT CHAR + case '\\': + ++in; + goto regchar; + + // FINISHED PARSING ONE OF POSSIBLY SEVERAL FILTERS? + case '\r': + case '\n': + case '\0': + // TITLE + // If user didn't specify a name, make one + // + if ( name[0] == '\0' ) { + sprintf(name, "%.*s Files", (int)sizeof(name)-10, wildcard); + } + // APPEND NEW FILTER TO LIST + if ( wildcard[0] ) { + // Add to filtername list + // Tab delimit if more than one. We later break + // tab delimited string into CFArray with + // CFStringCreateArrayBySeparatingStrings() + // + if ( _filt_total ) { + _filt_names = strapp(_filt_names, "\t"); + } + _filt_names = strapp(_filt_names, name); + + // Add filter to the pattern array + _filt_patt[_filt_total++] = strnew(wildcard); + } + // RESET + wildcard[0] = name[0] = '\0'; + mode = strchr(in, '\t') ? 'n' : 'w'; + // DONE? + if ( *in == '\0' ) return; // done + else continue; // not done yet, more filters + + // Parse all other chars + default: // handle all non-special chars + regchar: // handle regular char + switch ( mode ) { + case 'n': chrcat(name, *in); continue; + case 'w': chrcat(wildcard, *in); continue; + } + break; + } + } + //NOTREACHED +} + +// STATIC: FILTER CALLBACK +Boolean Fl_Native_File_Chooser::filter_proc_cb(AEDesc *theItem, + void *info, + void *callBackUD, + NavFilterModes filterMode) { + return((Fl_Native_File_Chooser*)callBackUD)->filter_proc_cb2( + theItem, info, callBackUD, filterMode); +} + +// FILTER CALLBACK +// Return true if match, +// false if no match. +// +Boolean Fl_Native_File_Chooser::filter_proc_cb2(AEDesc *theItem, + void *info, + void *callBackUD, + NavFilterModes filterMode) { + // All files chosen or no filters + if ( _filt_value == _filt_total ) return(true); + + FSSpec fsspec; + char pathname[4096]; + + // On fail, filter should return true by default + if ( AEDescToFSSpec(theItem, &fsspec) != noErr ) { + return(true); + } + FSSpecToPath(fsspec, pathname, sizeof(pathname)-1); + + if ( fl_filename_isdir(pathname) ) return(true); + if ( fl_filename_match(pathname, _filt_patt[_filt_value]) ) return(true); + else return(false); +} + +// SET PRESET FILE +// Value can be NULL for none. +// +void Fl_Native_File_Chooser::preset_file(const char* val) { + _preset_file = strfree(_preset_file); + _preset_file = strnew(val); +} + +// PRESET FILE +// Returned value can be NULL if none set. +// +const char* Fl_Native_File_Chooser::preset_file() { + return(_preset_file); +} + 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 @@ +// +// Fl_Native_File_Chooser_WINDOWS.H -- FLTK native OS file chooser widget +// +// Copyright 2004 by Greg Ercolano. +// April 2005 - API changes, improved filter processing by Nathan Vander Wilt +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +#ifndef _FL_NATIVE_FILE_BROWSER_H +#define _FL_NATIVE_FILE_BROWSER_H + +// #define _WIN32_WINNT 0x0501 // needed for OPENFILENAME's 'FlagsEx' +#include +#include // malloc +#include +#include // OPENFILENAME, GetOpenFileName() +#include // BROWSEINFO, SHBrowseForFolder() + +#define MAXFILTERS 80 + +class Fl_Native_File_Chooser { +public: + enum Type { + BROWSE_FILE = 0, + BROWSE_DIRECTORY, + BROWSE_MULTI_FILE, + BROWSE_MULTI_DIRECTORY, + BROWSE_SAVE_FILE, + BROWSE_SAVE_DIRECTORY + }; + enum Option { + NO_OPTIONS = 0x0000, // no options enabled + SAVEAS_CONFIRM = 0x0001, // Show native 'Save As' overwrite + // confirm dialog (if supported) + NEW_FOLDER = 0x0002, // Show 'New Folder' icon + // (if supported) + PREVIEW = 0x0004, // enable preview mode + }; +private: + int _btype; // kind-of browser to show() + int _options; // general options + OPENFILENAME _ofn; // GetOpenFileName() & GetSaveFileName() struct + BROWSEINFO _binf; // SHBrowseForFolder() struct + char **_pathnames; // array of pathnames + int _tpathnames; // total pathnames + char *_directory; // default pathname to use + char *_title; // title for window + char *_filter; // user-side search filter + char *_parsedfilt; // filter parsed for Windows dialog + int _nfilters; // number of filters parse_filter counted + char *_preset_file; // the file to preselect + char *_errmsg; // error message + + // Private methods + void errmsg(const char *msg); + + void clear_pathnames(); + void set_single_pathname(const char *s); + void add_pathname(const char *s); + + void FreePIDL(ITEMIDLIST *pidl); + void ClearOFN(); + void ClearBINF(); + void Win2Unix(char *s); + void Unix2Win(char *s); + int showfile(); + static int CALLBACK Dir_CB(HWND win, UINT msg, LPARAM param, LPARAM data); + int showdir(); + + void parse_filter(const char *); + void clear_filters(); + void add_filter(const char *, const char *); + +public: + Fl_Native_File_Chooser(int val = BROWSE_FILE); + ~Fl_Native_File_Chooser(); + + // Public methods + void type(int val); + int type() const; + void options(int); + int options() const; + int count() const; + const char *filename() const; + const char *filename(int i) const; + void directory(const char *val); + const char *directory() const; + void title(const char *val); + const char *title() const; + const char *filter() const; + void filter(const char *val); + int filters() const { return _nfilters; } + void filter_value(int i); + int filter_value() const; + void preset_file(const char *); + const char *preset_file() const; + const char *errmsg() const; + int show(); +}; + +#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 @@ +// +// Fl_Native_File_Chooser_WINDOWS.cxx -- FLTK native OS file chooser widget +// +// Copyright 2004 by Greg Ercolano. +// April 2005 - API changes, improved filter processing by Nathan Vander Wilt +// +// This library is free software; you can redistribute it and/or +// modify it under the terms of the GNU Library General Public +// License as published by the Free Software Foundation; either +// version 2 of the License, or (at your option) any later version. +// +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// Library General Public License for more details. +// +// You should have received a copy of the GNU Library General Public +// License along with this library; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA. +// +// Please keep code 80 column compliant. +// +// 10 20 30 40 50 60 70 +// | | | | | | | +// 4567890123456789012345678901234567890123456789012345678901234567890123456789 +// + +// http://www.codeproject.com/dialog/selectfolder.asp - any application to multi-folder implementation? + +#include +#include // debugging +#include "common.cxx" // strnew/strfree/strapp/chrcat + +#define LCURLY_CHR '{' +#define RCURLY_CHR '}' +#define LBRACKET_CHR '[' +#define RBRACKET_CHR ']' +#ifndef BIF_NONEWFOLDERBUTTON +#define BIF_NONEWFOLDERBUTTON 0x200 +#endif +// STATIC: PRINT WINDOWS 'DOUBLE NULL' STRING (DEBUG) +/* +static void dnullprint(char *wp) { + if ( ! wp ) return; + for ( int t=0; true; t++ ) { + if ( wp[t] == '\0' && wp[t+1] == '\0' ) { + printf("\\0\\0"); + fflush(stdout); + return; + } else if ( wp[t] == '\0' ) { + printf("\\0"); + } else { + printf("%c",wp[t]); + } + } +} +*/ +// RETURN LENGTH OF DOUBLENULL STRING +// Includes single nulls in count, excludes trailing doublenull. +// +// 1234 567 +// |||/\||| +// IN: "one\0two\0\0" +// OUT: 7 +// +static int dnulllen(const char *wp) { + int len = 0; + while ( ! ( *(wp+0) == 0 && *(wp+1) == 0 ) ) + { ++wp; ++len; } + return(len); +} + +// STATIC: Append a string to another, leaving terminated with DOUBLE NULL. +// Automatically handles extending length of string. +// wp can be NULL (a new wp will be allocated and initialized). +// string must be NULL terminated. +// The pointer wp may be modified on return. +// +static void dnullcat(char*&wp, const char *string, int n = -1 ) { + //DEBUG printf("DEBUG: dnullcat IN: <"); dnullprint(wp); printf(">\n"); + int inlen = ( n < 0 ) ? strlen(string) : n; + if ( ! wp ) { + wp = new char[inlen + 4]; + *(wp+0) = '\0'; + *(wp+1) = '\0'; + } else { + int wplen = dnulllen(wp); + // Make copy of wp into larger buffer + char *tmp = new char[wplen + inlen + 4]; + memcpy(tmp, wp, wplen+2); // copy of wp plus doublenull + delete [] wp; // delete old wp + wp = tmp; // use new copy + //DEBUG printf("DEBUG: dnullcat COPY: <"); dnullprint(wp); printf("> (wplen=%d)\n", wplen); + } + + // Find end of double null string + // *wp2 is left pointing at second null. + // + char *wp2 = wp; + if ( *(wp2+0) != '\0' && *(wp2+1) != '\0' ) { + for ( ; 1; wp2++ ) + if ( *(wp2+0) == '\0' && *(wp2+1) == '\0' ) + { wp2++; break; } + } + + if ( n == -1 ) n = strlen(string); + strncpy(wp2, string, n); + + // Leave string double-null terminated + *(wp2+n+0) = '\0'; + *(wp2+n+1) = '\0'; + //DEBUG printf("DEBUG: dnullcat OUT: <"); dnullprint(wp); printf(">\n\n"); +} + +// CTOR +Fl_Native_File_Chooser::Fl_Native_File_Chooser(int val) { + _btype = val; + _options = NO_OPTIONS; + memset((void*)&_ofn, 0, sizeof(OPENFILENAME)); + _ofn.lStructSize = sizeof(OPENFILENAME); + _ofn.hwndOwner = NULL; + memset((void*)&_binf, 0, sizeof(BROWSEINFO)); + _pathnames = NULL; + _tpathnames = 0; + _directory = NULL; + _title = NULL; + _filter = NULL; + _parsedfilt = NULL; + _nfilters = 0; + _preset_file = NULL; + _errmsg = NULL; +} + +// DTOR +Fl_Native_File_Chooser::~Fl_Native_File_Chooser() { + //_pathnames // managed by clear_pathnames() + //_tpathnames // managed by clear_pathnames() + _directory = strfree(_directory); + _title = strfree(_title); + _filter = strfree(_filter); + //_parsedfilt // managed by clear_filters() + //_nfilters // managed by clear_filters() + _preset_file = strfree(_preset_file); + _errmsg = strfree(_errmsg); + clear_filters(); + clear_pathnames(); + ClearOFN(); + ClearBINF(); +} + +// SET TYPE OF BROWSER +void Fl_Native_File_Chooser::type(int val) { + _btype = val; +} + +// GET TYPE OF BROWSER +int Fl_Native_File_Chooser::type() const { + return( _btype ); +} + +// SET OPTIONS +void Fl_Native_File_Chooser::options(int val) { + _options = val; +} + +// GET OPTIONS +int Fl_Native_File_Chooser::options() const { + return(_options); +} + +// PRIVATE: SET ERROR MESSAGE +void Fl_Native_File_Chooser::errmsg(const char *val) { + _errmsg = strfree(_errmsg); + _errmsg = strnew(val); +} + +// FREE PATHNAMES ARRAY, IF IT HAS ANY CONTENTS +void Fl_Native_File_Chooser::clear_pathnames() { + if ( _pathnames ) { + while ( --_tpathnames >= 0 ) { + _pathnames[_tpathnames] = strfree(_pathnames[_tpathnames]); + } + delete [] _pathnames; + _pathnames = NULL; + } + _tpathnames = 0; +} + +// SET A SINGLE PATHNAME +void Fl_Native_File_Chooser::set_single_pathname(const char *s) { + clear_pathnames(); + _pathnames = new char*[1]; + _pathnames[0] = strnew(s); + _tpathnames = 1; +} + +// ADD PATHNAME TO EXISTING ARRAY +void Fl_Native_File_Chooser::add_pathname(const char *s) { + if ( ! _pathnames ) { + // Create first element in array + ++_tpathnames; + _pathnames = new char*[_tpathnames]; + } else { + // Grow array by 1 + char **tmp = new char*[_tpathnames+1]; // create new buffer + memcpy((void*)tmp, (void*)_pathnames, sizeof(char*)*_tpathnames); // copy old + delete [] _pathnames; // delete old + _pathnames = tmp; // use new + ++_tpathnames; + } + _pathnames[_tpathnames-1] = strnew(s); +} + +// FREE A PIDL (Pointer to IDentity List) +void Fl_Native_File_Chooser::FreePIDL(ITEMIDLIST *pidl) { + IMalloc *imalloc = NULL; + if ( SUCCEEDED(SHGetMalloc(&imalloc)) ) + { imalloc->Free(pidl); imalloc->Release(); imalloc = NULL; } +} + +// CLEAR MICROSOFT OFN (OPEN FILE NAME) CLASS +void Fl_Native_File_Chooser::ClearOFN() { + int temp; + // Free any previously allocated lpstrFile before zeroing out _ofn + if ( _ofn.lpstrFile ) + { _ofn.lpstrFile = strfree((char*)_ofn.lpstrFile); } + if ( _ofn.lpstrInitialDir ) + { _ofn.lpstrInitialDir = (LPCSTR)strfree((char*)_ofn.lpstrInitialDir); } + if ( _ofn.lpstrFile ) + { _ofn.lpstrFile = strfree(_ofn.lpstrFile); } + _ofn.lpstrFilter = NULL; // (deleted elsewhere) + temp = _ofn.nFilterIndex; // keep the filter_value + memset((void*)&_ofn, 0, sizeof(_ofn)); + _ofn.lStructSize = sizeof(OPENFILENAME); + _ofn.nFilterIndex = temp; +} + +// CLEAR MICROSOFT BINF (BROWSER INFO) CLASS +void Fl_Native_File_Chooser::ClearBINF() { + if ( _binf.pidlRoot ) { + FreePIDL((ITEMIDLIST*)_binf.pidlRoot); + _binf.pidlRoot = NULL; + } + memset((void*)&_binf, 0, sizeof(_binf)); +} + +// CONVERT WINDOWS BACKSLASHES TO UNIX FRONTSLASHES +void Fl_Native_File_Chooser::Win2Unix(char *s) { + for ( ; *s; s++ ) + if ( *s == '\\' ) *s = '/'; +} + +// CONVERT UNIX FRONTSLASHES TO WINDOWS BACKSLASHES +void Fl_Native_File_Chooser::Unix2Win(char *s) { + for ( ; *s; s++ ) + if ( *s == '/' ) *s = '\\'; +} + +// SHOW FILE BROWSER +int Fl_Native_File_Chooser::showfile() { + ClearOFN(); + clear_pathnames(); + size_t fsize = 2048; + _ofn.Flags |= OFN_NOVALIDATE; // prevent disabling of front slashes + _ofn.Flags |= OFN_HIDEREADONLY; // hide goofy readonly flag + // USE NEW BROWSER + _ofn.Flags |= OFN_EXPLORER; // use newer explorer windows +// // USE OLD BROWSER +// _ofn.lpfnHook = MyHook; +// _ofn.Flags |= OFN_ENABLEHOOK; + _ofn.Flags |= OFN_ENABLESIZING; // allow window to be resized (hey, why not?) + + switch ( _btype ) { + case BROWSE_DIRECTORY: + case BROWSE_MULTI_DIRECTORY: + case BROWSE_SAVE_DIRECTORY: + abort(); // never happens: handled by showdir() + case BROWSE_FILE: + fsize = 65536; // XXX: there must be a better way + break; + case BROWSE_MULTI_FILE: + _ofn.Flags |= OFN_ALLOWMULTISELECT; + fsize = 65536; // XXX: there must be a better way + break; + case BROWSE_SAVE_FILE: + if ( options() & SAVEAS_CONFIRM && type() == BROWSE_SAVE_FILE ) { + _ofn.Flags |= OFN_OVERWRITEPROMPT; + } + break; + } + // SPACE FOR RETURNED FILENAME + _ofn.lpstrFile = new char[fsize]; + _ofn.nMaxFile = fsize-1; + _ofn.lpstrFile[0] = '\0'; + _ofn.lpstrFile[1] = '\0'; + // PARENT WINDOW + _ofn.hwndOwner = GetForegroundWindow(); + // DIALOG TITLE + _ofn.lpstrTitle = _title ? _title : NULL; + // FILTER + _ofn.lpstrFilter = _parsedfilt ? _parsedfilt : NULL; + // PRESET FILE + // If set, supercedes _directory. See KB Q86920 for details + // + if ( _preset_file ) { + int len = strlen(_preset_file); + char *strfile = new char[MAX_PATH]; // as per KB 222003 >8( + strcpy(strfile, _preset_file); + strfile[len+0] = '\0'; // (multiselect needs dnull) + strfile[len+1] = '\0'; + Unix2Win(strfile); + _ofn.lpstrFile = strfile; + _ofn.nMaxFile = MAX_PATH; // as per KB 222003 >8( + } + if ( _directory ) { + // PRESET DIR + // XXX: See KB Q86920 for doc bug: + // http://support.microsoft.com/default.aspx?scid=kb;en-us;86920 + // + if ( _directory ) { + _ofn.lpstrInitialDir = strnew(_directory); + Unix2Win((char*)_ofn.lpstrInitialDir); + } + } + // OPEN THE DIALOG WINDOW + int err; + if ( _btype == BROWSE_SAVE_FILE ) { + err = GetSaveFileName(&_ofn); + } else { + err = GetOpenFileName(&_ofn); + } + if ( err == 0 ) { + // EXTENDED ERROR CHECK + int err = CommDlgExtendedError(); + // CANCEL? + if ( err == 0 ) + return(1); // user hit 'cancel' + // AN ERROR OCCURRED + char msg[80]; + sprintf(msg, "CommDlgExtendedError() code=%d", err); + errmsg(msg); + return(-1); + } + // PREPARE PATHNAMES FOR RETURN + switch ( _btype ) { + case BROWSE_FILE: + case BROWSE_SAVE_FILE: + set_single_pathname(_ofn.lpstrFile); + Win2Unix(_pathnames[_tpathnames-1]); + break; + case BROWSE_MULTI_FILE: { + // EXTRACT MULTIPLE FILENAMES + const char *dirname = _ofn.lpstrFile; + int dirlen = strlen(dirname); + if ( dirlen > 0 ) { + char pathname[2048]; + + // WALK STRING SEARCHING FOR 'DOUBLE-NULL' + // eg. "/dir/name\0foo1\0foo2\0foo3\0\0" + // + for ( const char *s = _ofn.lpstrFile + dirlen + 1; + *s; s+= (strlen(s)+1)) { + strcpy(pathname, dirname); + strcat(pathname, "\\"); + strcat(pathname, s); + add_pathname(pathname); + Win2Unix(_pathnames[_tpathnames-1]); + } + } + // XXX + // Work around problem where pasted forward-slash pathname + // into the file browser causes new "Explorer" interface + // not to grok forward slashes, passing back as a 'filename'..! + // + if ( _tpathnames == 0 ) { + add_pathname(dirname); + Win2Unix(_pathnames[_tpathnames-1]); + } + break; + } + case BROWSE_DIRECTORY: + case BROWSE_MULTI_DIRECTORY: + case BROWSE_SAVE_DIRECTORY: + abort(); // not here + } + return(0); +} + +// Used by SHBrowseForFolder(), sets initial selected dir. +// Ref: Usenet: microsoft.public.vc.mfc, Dec 8 2000, 1:38p David Lowndes +// Subject: How to specify to select an initial folder .." +// +int CALLBACK Fl_Native_File_Chooser::Dir_CB(HWND win, UINT msg, LPARAM param, LPARAM data) { + switch (msg) { + case BFFM_INITIALIZED: + if (data) ::SendMessage(win, BFFM_SETSELECTION, TRUE, data); + break; + case BFFM_SELCHANGED: + TCHAR path[MAX_PATH]; + if ( SHGetPathFromIDList((ITEMIDLIST*)param, path) ) { + ::SendMessage(win, BFFM_ENABLEOK, 0, 1); + } else { + //disable ok button if not a path + ::SendMessage(win, BFFM_ENABLEOK, 0, 0); + } + break; + case BFFM_VALIDATEFAILED: + // we could pop up an annoying message here. + // also needs set ulFlags |= BIF_VALIDATE + break; + default: + break; + } + return(0); +} + +// SHOW DIRECTORY BROWSER +int Fl_Native_File_Chooser::showdir() { + OleInitialize(NULL); // init needed by BIF_USENEWUI + ClearBINF(); + clear_pathnames(); + // PARENT WINDOW + _binf.hwndOwner = GetForegroundWindow(); + // DIALOG TITLE + _binf.lpszTitle = _title ? _title : NULL; + // FLAGS + _binf.ulFlags =0; // initialize + + // TBD: make sure matches to runtime system, if need be. + //( what if _WIN32_IE doesn't match system? does the program not run? ) + // TBD: match all 3 types of directories + +#if defined(BIF_NONEWFOLDERBUTTON) // Version 6.0 + if ( _btype == BROWSE_DIRECTORY ) _binf.ulFlags &= !BIF_NONEWFOLDERBUTTON; + _binf.ulFlags |= BIF_USENEWUI | BIF_SHAREABLE | BIF_RETURNONLYFSDIRS; +#elif defined(BIF_USENEWUI) // Version 5.0 + if ( _btype == BROWSE_DIRECTORY ) _binf.ulFlags |= BIF_EDITBOX; + else if ( _btype == BROWSE_SAVE_DIRECTORY ) _binf.ulFlags |= BIF_USENEWUI; + _binf.ulFlags |= BIF_SHAREABLE | BIF_RETURNONLYFSDIRS; +#elif defined(BIF_EDITBOX) // Version 4.71 + _binf.ulFlags |= BIF_RETURNONLYFSDIRS | BIF_EDITBOX; +#else // Version Old + _binf.ulFlags |= BIF_RETURNONLYFSDIRS; +#endif + + + // BUFFER + char displayname[MAX_PATH]; + _binf.pszDisplayName = displayname; + // PRESET DIR + char presetname[MAX_PATH]; + if ( _directory ) { + strcpy(presetname, _directory); + Unix2Win(presetname); + _binf.lParam = (LPARAM)presetname; + } + else _binf.lParam = 0; + _binf.lpfn = Dir_CB; + // OPEN BROWSER + ITEMIDLIST *pidl = SHBrowseForFolder(&_binf); + // CANCEL? + if ( pidl == NULL ) return(1); + + // GET THE PATHNAME(S) THE USER SELECTED + // TBD: expand NetHood shortcuts from this PIDL?? + // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/functions/shbrowseforfolder.asp + + TCHAR path[MAX_PATH]; + if ( SHGetPathFromIDList(pidl, path) ) + { Win2Unix(path); add_pathname(path); } + FreePIDL(pidl); + if ( !strlen(path) ) return(1); // don't return empty pathnames + return(0); +} + +// RETURNS: +// 0 - user picked a file +// 1 - user cancelled +// -1 - failed; errmsg() has reason +// +int Fl_Native_File_Chooser::show() { + if ( _btype == BROWSE_DIRECTORY || + _btype == BROWSE_MULTI_DIRECTORY || + _btype == BROWSE_SAVE_DIRECTORY ) + return(showdir()); + else + return(showfile()); +} + +// RETURN ERROR MESSAGE +const char *Fl_Native_File_Chooser::errmsg() const { + return(_errmsg ? _errmsg : "No error"); +} + +// GET FILENAME +const char* Fl_Native_File_Chooser::filename() const { + if ( _pathnames && _tpathnames > 0 ) return(_pathnames[0]); + return(""); +} + +// GET FILENAME FROM LIST OF FILENAMES +const char* Fl_Native_File_Chooser::filename(int i) const { + if ( _pathnames && i < _tpathnames ) return(_pathnames[i]); + return(""); +} + +// GET TOTAL FILENAMES CHOSEN +int Fl_Native_File_Chooser::count() const { + return(_tpathnames); +} + +// PRESET PATHNAME +// Can be NULL if no preset is desired. +// +void Fl_Native_File_Chooser::directory(const char *val) { + _directory = strfree(_directory); + _directory = strnew(val); +} + +// GET PRESET PATHNAME +// Can return NULL if none set. +// +const char *Fl_Native_File_Chooser::directory() const { + return(_directory); +} + +// SET TITLE +// Can be NULL if no title desired. +// +void Fl_Native_File_Chooser::title(const char *val) { + _title = strfree(_title); + _title = strnew(val); +} + +// GET TITLE +// Can return NULL if none set. +// +const char *Fl_Native_File_Chooser::title() const { + return(_title); +} + +// SET FILTER +// Can be NULL if no filter needed +// +void Fl_Native_File_Chooser::filter(const char *val) { + _filter = strfree(_filter); + clear_filters(); + if ( val ) { + _filter = strnew(val); + parse_filter(_filter); + } + add_filter("All Files", "*.*"); // always include 'all files' option + +#ifdef DEBUG + nullprint(_parsedfilt); +#endif /*DEBUG*/ +} + +// GET FILTER +// Can return NULL if none set. +// +const char *Fl_Native_File_Chooser::filter() const { + return(_filter); +} + +// CLEAR FILTERS +void Fl_Native_File_Chooser::clear_filters() { + _nfilters = 0; + _parsedfilt = strfree(_parsedfilt); +} + +// ADD A FILTER +void Fl_Native_File_Chooser::add_filter( + const char *name_in, // name of filter (optional: can be null) + const char *winfilter // windows style filter (eg. "*.cxx;*.h") + ) { + // No name? Make one.. + char name[1024]; + if ( !name_in || name_in[0] == '\0' ) { + sprintf(name, "%.*s Files", sizeof(name)-10, winfilter); + } else { + sprintf(name, "%.*s", sizeof(name)-10, name_in); + } + dnullcat(_parsedfilt, name); + dnullcat(_parsedfilt, winfilter); + //DEBUG printf("DEBUG: ADD FILTER name=<%s> winfilter=<%s>\n", name, winfilter); +} + +// CONVERT FLTK STYLE PATTERN MATCHES TO WINDOWS 'DOUBLENULL' PATTERN +// Handles: +// IN OUT +// ----------- ----------------------------- +// *.{ma,mb} "*.{ma,mb} Files\0*.ma;*.mb\0\0" +// *.[abc] "*.[abc] Files\0*.a;*.b;*.c\0\0" +// *.txt "*.txt Files\0*.txt\0\0" +// C Files\t*.[ch] "C Files\0*.c;*.h\0\0" +// +// Example: +// IN: "*.{ma,mb}" +// OUT: "*.ma;*.mb Files\0*.ma;*.mb\0All Files\0*.*\0\0" +// --------------- --------- --------- --- +// | | | | +// Title Wildcards Title Wildcards +// +// Parsing Mode: +// IN:"C Files\t*.{cxx,h}" +// ||||||| ||||||||| +// mode: nnnnnnn ww{{{{{{{ +// \_____/ \_______/ +// Name Wildcard +// +void Fl_Native_File_Chooser::parse_filter(const char *in) { + clear_filters(); + if ( ! in ) return; + + int has_name = strchr(in, '\t') ? 1 : 0; + //const char *savein = in; + + char mode = has_name ? 'n' : 'w'; // parse mode: n=name, w=wildcard + int nwildcards = 0; + char wildcards[MAXFILTERS][1024]; // parsed wildcards (can be several) + char wildprefix[512] = ""; + char name[512] = ""; + + // Init + int t; + for ( t=0; t name=<%s> wildprefix=<%s> nwildcards=%d wildcards[n]=<%s>\n", + //// *in, mode, name, wildprefix, nwildcards, wildcards[nwildcards]); + + switch (*in) { + case ',': + case '|': + if ( mode == LCURLY_CHR ) { + // create new wildcard, copy in prefix + strcat(wildcards[nwildcards++], wildprefix); + continue; + } else { + goto regchar; + } + continue; + + // FINISHED PARSING A NAME? + case '\t': + if ( mode != 'n' ) goto regchar; + // finish parsing name? switch to wildcard mode + mode = 'w'; + break; + + // ESCAPE NEXT CHAR + case '\\': + ++in; + goto regchar; + + // FINISHED PARSING ONE OF POSSIBLY SEVERAL FILTERS? + case '\r': + case '\n': + case '\0': + { + if ( mode == 'w' ) { // finished parsing wildcard? + if ( nwildcards == 0 ) { + strcpy(wildcards[nwildcards++], wildprefix); + } + // Append wildcards in Microsoft's "*.one;*.two" format + char comp[4096] = ""; + for ( t=0; t 0 ) { + chrcat(wildcards[nwildcards-1], *in); + } + continue; + + case 'n': + chrcat(name, *in); + continue; + + case 'w': + chrcat(wildprefix, *in); + for ( t=0; t} {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +decl {\#include } {public +} + +class WidgetPDial {: {public Fl_Dial} +} { + Function {WidgetPDial(int x,int y, int w, int h, const char *label=0):Fl_Dial(x,y,w,h,label)} {} { + code {oldvalue=0.0;} {} + } + Function {handle(int event)} {return_type int + } { + code {double dragsize,v,min=minimum(),max=maximum(); +int my; + +switch (event){ +case FL_PUSH:oldvalue=value(); +case FL_DRAG: + my=-(Fl::event_y()-y()-h()/2); + + dragsize=200.0; + if (Fl::event_state(FL_BUTTON1)==0) dragsize*=10; + v=oldvalue+my/dragsize*(max-min); + if (vmax) v=max; + + //printf("%d %g %g\\n",my,v,oldvalue); + value(v); + value_damage(); + if (this->when()!=0) do_callback(); + return(1); + break; +case FL_RELEASE: + if (this->when()==0) do_callback(); + return(1); + break; +}; +return(0);} {selected + } + } + Function {drawgradient(int cx,int cy,int sx,double m1,double m2)} {return_type void + } { + code {for (int i=(int)(m1*sx);i<(int)(m2*sx);i++){ + double tmp=1.0-pow(i*1.0/sx,2.0); + pdialcolor(140+(int) (tmp*90),140+(int)(tmp*90),140+(int) (tmp*100)); + fl_arc(cx+sx/2-i/2,cy+sx/2-i/2,i,i,0,360); +};} {} + } + Function {draw()} {} { + code {int cx=x(),cy=y(),sx=w(),sy=h(); + + +//clears the button face +pdialcolor(190,190,200); +fl_pie(cx-1,cy-1,sx+2,sy+2,0,360); + +//Draws the button face (gradinet) +drawgradient(cx,cy,sx,0.5,1.0); + +double val=(value()-minimum())/(maximum()-minimum()); + +//draws the scale +pdialcolor(220,220,250); +double a1=angle1(),a2=angle2(); +for (int i=0;i<12;i++){ + double a=-i/12.0*360.0-val*(a2-a1)-a1; + fl_pie(cx,cy,sx,sy,a+270-3,a+3+270); +}; + +drawgradient(cx,cy,sx,0.0,0.75); + +//draws the value +double a=-(a2-a1)*val-a1; + + + + + +//draws the max and min points +pdialcolor(0,100,200); +int xp=(int)(cx+sx/2.0+sx/2.0*sin(angle1()/180.0*3.141592)); +int yp=(int)(cy+sy/2.0+sy/2.0*cos(angle1()/180.0*3.141592)); +fl_pie(xp-2,yp-2,4,4,0,360); + +xp=(int)(cx+sx/2.0+sx/2.0*sin(angle2()/180.0*3.141592)); +yp=(int)(cy+sy/2.0+sy/2.0*cos(angle2()/180.0*3.141592)); +fl_pie(xp-2,yp-2,4,4,0,360); + + + + + +fl_push_matrix(); + + fl_translate(cx+sx/2,cy+sy/2); + fl_rotate(a-90.0); + + fl_translate(sx/2,0); + + + fl_begin_polygon(); + pdialcolor(0,0,0); + fl_vertex(-10,-4); + fl_vertex(-10,4); + fl_vertex(0,0); + fl_end_polygon(); + + +fl_pop_matrix();} {} + } + Function {pdialcolor(int r,int g,int b)} {} { + code {if (active_r()) fl_color(r,g,b); + else fl_color(160-(160-r)/3,160-(160-b)/3,160-(160-b)/3);} {} + } + decl {double oldvalue;} {} +} 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 @@ +// COPY A STRING WITH 'new' +// Value can be NULL +// +static char *strnew(const char *val) +{ + if ( val == NULL ) + return(NULL); + + char *s = new char[strlen(val)+1]; + strcpy(s, val); + + return(s); +} + +// FREE STRING CREATED WITH strnew(), NULLS OUT STRING +// Value can be NULL +// +static char *strfree(char *val) +{ + if ( val ) + delete [] val; + + return(NULL); +} + +// 'DYNAMICALLY' APPEND ONE STRING TO ANOTHER +// Returns newly allocated string, or NULL +// if s && val == NULL. +// 's' can be NULL; returns a strnew(val). +// 'val' can be NULL; s is returned unmodified. +// +// Usage: +// char *s = strnew("foo"); // s = "foo" +// s = strapp(s, "bar"); // s = "foobar" +// +#ifndef WINDOWS +static char *strapp(char *s, const char *val) +{ + if ( ! val ) + return(s); // Nothing to append? return s + + if ( ! s ) + return(strnew(val)); // New string? return copy of val + + char *news = new char[strlen(s)+strlen(val)+1]; + strcpy(news, s); + strcat(news, val); + + delete [] s; // delete old string + return(news); // return new copy +} +#endif +// APPEND A CHARACTER TO A STRING +static void chrcat(char *s, char c) +{ + char tmp[2] = { c, '\0' };; + strcat(s, tmp); +} + + 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 @@ +#ifdef WINDOWS +# define __sint64 signed __int64 +# define __uint64 unsigned __int64 +#else +# define __sint64 signed long long +# define __uint64 unsigned long long +#endif + +#define __sint32 signed long +#define __uint32 unsigned long + 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 @@ +#include +#include "convertlib.h" + +bool Convert::isnibble(string x) +{ + if ((x >= "0") && (x <= "9")) return true; + if ((x >= "a") && (x <= "f")) return true; + if ((x >= "A") && (x <= "F")) return true; + return false; +} + +string* Convert::byte2hex(unsigned char x) +{ + int b = x % 16; + int a = x >> 4; + + string hex = "0123456789ABCDEF"; + string * newst = new string(""); + *newst = *newst + hex.substr(a, 1); + *newst = *newst + hex.substr(b, 1); + return newst; +} + +long Convert::str2long(string decstr) +{ + return strtol(decstr.c_str(), 0, 10); +} + +double Convert::str2dbl(string decstr) +{ + return strtod(decstr.c_str(), 0); +} + +string* Convert::int2str(int x, unsigned int pad, string padchar) +{ + string* newst = int2str(x); + + if (pad > 1) + { + while (newst->length() < pad) + { + *newst = padchar + *newst; + } + } + + return newst; +} + +string* Convert::int64tostr(__sint64 x) +{ + bool isneg=false; + string * newst = new string(""); + if (x == 0) + { + *newst = "0"; + } + else + { + if (x<0) + { + isneg=true; + x=0-x; + } + while (x != 0) + { + long long digit = x % (long long) 10; + string dec = "0123456789"; + *newst = dec.substr(digit, 1) + *newst; + + x -= (long long) (x % (long long) 10); + x /= (long long) 10; + } + } + if (isneg) + { + *newst="-"+*newst; + } + return newst; +} + +string* Convert::int2str(int x) +{ + long long y = x; + return int64tostr(y); +} + +string* Convert::int32tostr(__uint32 x) +{ + long long y = x; + return int64tostr(y); +} + +long Convert::hex2long(string hexstr) +{ + return strtol(hexstr.c_str(), 0, 16); +} + +unsigned char Convert::hex2byte(string hexstr) +{ + long x = hex2long(hexstr); + return (unsigned char) x % 256; +} + +unsigned char Convert::safebyte(unsigned char x) +{ + if (x < 32) return '.'; + return x; +} + +string* Convert::int64tohex(__sint64 x) +{ + __sint64 q = x; + unsigned char a = q % 256; q = q >> 8; + unsigned char b = q % 256; q = q >> 8; + unsigned char c = q % 256; q = q >> 8; + unsigned char d = q % 256; q = q >> 8; + unsigned char e = q % 256; q = q >> 8; + unsigned char f = q % 256; q = q >> 8; + unsigned char g = q % 256; q = q >> 8; + unsigned char h = q % 256; + string* b2h8 = byte2hex(h); + string* b2h7 = byte2hex(g); + string* b2h6 = byte2hex(f); + string* b2h5 = byte2hex(e); + string* b2h4 = byte2hex(d); + string* b2h3 = byte2hex(c); + string* b2h2 = byte2hex(b); + string* b2h1 = byte2hex(a); + string* newst = new string(); + *newst += *b2h8 + *b2h7 + ":" + *b2h6 + *b2h5 + "." + *b2h4 + *b2h3 + ":" + *b2h2 + *b2h1; + delete (b2h1); + delete (b2h2); + delete (b2h3); + delete (b2h4); + delete (b2h5); + delete (b2h6); + delete (b2h7); + delete (b2h8); + return newst; +} + +string* Convert::int32tohex(unsigned long x) +{ + __sint64 q = x; + unsigned char a = q % 256; q = q >> 8; + unsigned char b = q % 256; q = q >> 8; + unsigned char c = q % 256; q = q >> 8; + unsigned char d = q % 256; q = q >> 8; + string* b2h4 = byte2hex(d); + string* b2h3 = byte2hex(c); + string* b2h2 = byte2hex(b); + string* b2h1 = byte2hex(a); + string* newst = new string(); + *newst += *b2h4 + *b2h3 + ":" + *b2h2 + *b2h1; + delete (b2h1); + delete (b2h2); + delete (b2h3); + delete (b2h4); + return newst; +} + +unsigned int Convert::getint24(unsigned char * buf, int loc) +{ + unsigned int q = 0; + + q = buf[loc + 2] + + (buf[loc + 1] << 8) + + (buf [loc + 0] << 16); + return q; +} + + +unsigned int Convert::getint32(unsigned char * buf, int loc) +{ + unsigned int q = 0; + + q = buf[loc + 3] + + (buf[loc + 2] << 8) + + (buf [loc + 1] << 16) + + (buf [loc] << 24); + return q; +} + +void Convert::setint32(unsigned char * buf, int loc, __uint32 newval) +{ + buf[loc + 0] = (newval >> 24) % 256; + buf[loc + 1] = (newval >> 16) % 256; + buf[loc + 2] = (newval >> 8) % 256; + buf[loc + 3] = newval % 256; +} + +void Convert::setfloat80(unsigned char * buf, int loc, __uint32 newval) +{ + /* Thanks, Erik */ + unsigned int mask = 0x40000000 ; + int count ; + + for (int i=0;i<10;i++) + { + buf[loc+i]=0; + } + if (newval <= 1) + { buf[loc+0] = 0x3F ; + buf[loc+1] = 0xFF ; + buf[loc+2] = 0x80 ; + return ; + } ; + + buf[loc+0] = 0x40 ; + + if (newval >= mask) + { buf[loc+1] = 0x1D ; + return ; + } ; + + for (count = 0 ; count <= 32 ; count ++) + { if (newval & mask) + break ; + mask >>= 1 ; + } ; + + newval <<= count + 1 ; + buf[loc+1] = 29 - count ; + buf[loc+2] = (newval >> 24) & 0xFF ; + buf[loc+3] = (newval >> 16) & 0xFF ; + buf[loc+4] = (newval >> 8) & 0xFF ; + buf[loc+5] = newval & 0xFF ; + return; +} + +string* Convert::readstring(unsigned char * orig, int offset, int len) +{ + string * newst = new string(""); + int i; + + for (i = offset; i < offset + len; i++) + { + if (i >= offset + len) + return newst; + + if (orig[i] == 0) break; + *newst += orig[i]; + } + + return newst; +} + +string* Convert::padright(string & strinput, int inlen, string strpad) +{ + int currlen = strinput.length(); + + if (currlen > inlen) + { + strinput=strinput.substr(0,inlen); + return new string(strinput); + } + + int pad = inlen - currlen; + if (pad > 0) + { + for (int i = 0; i < pad; i++) + { + strinput += strpad; + } + } + + return new string(strinput); +} + +string* Convert::padleft(string & strinput, int inlen, string strpad) +{ + int currlen = strinput.length(); + + if (currlen > inlen) + { + return new string(strinput.substr(0, inlen)); + } + + int pad = inlen - currlen; + if (pad > 0) + { + string strtmp = ""; + for (int i = 0; i < pad; i++) + { + strtmp += strpad; + } + strinput = strtmp + strinput; + } + return new string(strinput); +} + +string* Convert::trim(string* strinput) +{ + if (strinput->length() == 0) + { + string* x = new string(""); + return x; + } + + string* strresult = new string(*strinput); + while (strresult->substr(0, 1) == " ") + { + *strresult = strresult->substr(1, strresult->length() - 1); + } + + while (strresult->substr(strresult->length() - 1, 1) == " ") + { + *strresult = strresult->substr(0, strresult->length() - 1); + } + return strresult; +} 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 @@ +#ifndef __convert_h__ +#define __convert_h__ + +using namespace std; + +#include "config.h" +#include +#include + +class Convert +{ + public: + Convert() {}; + ~Convert() {}; + + static bool isnibble(string x); + static long str2long(string hexstr); + static double str2dbl(string hexstr); + static long hex2long(string hexstr); + static string* byte2hex(unsigned char x); + static string* int2str(int x,unsigned int pad,string padchar); + static string* int2str(int x); + static string* int32tostr(__uint32 x); + static string* int64tostr(__sint64 x); + static string* int64tohex(__sint64 x); + static string* int32tohex(unsigned long x); + static string* readstring(unsigned char * orig,int offset,int len); + static string* padright(string & strinput,int inlen,string strpad); + static string* padleft(string & strinput,int inlen,string strpad); + static unsigned int getint32(unsigned char * buf,int loc); + static unsigned int getint24(unsigned char * buf,int loc); + static void setint32(unsigned char * buf,int loc,__uint32 newval); + static void setfloat80(unsigned char * buf, int loc, __uint32 newval); /* Only for use in AIFF files */ + static unsigned char hex2byte(string hexstr); + static unsigned char safebyte(unsigned char x); + static string* trim(string* strinput); +}; + +#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 @@ +#include "hd24devicenamegenerator.h" +#define DEVGENDEBUG 0 +#include +#include +#include +#ifdef DARWIN +#include +#else +#include +#endif +#include +#include +int endswith(const char* str, const char* end) +{ +#if (DEVGENDEBUG==1) +cout << "endswith("<d_type != isFile) continue; + + if (!( endswith(DirEntry->d_name,".h24") + ||endswith(DirEntry->d_name,".H24"))) continue; + + foundcount++; + + if (filelist==NULL) + { + filelist=new vector(); + } + string* fname=new string(dirname); + *fname+=DirEntry->d_name; + filelist->push_back(*fname); +#if (DEVGENDEBUG==1) + cout <<"Found a File : " << *fname << endl; +#endif + delete fname; + + // validity of file image will be extablished by hd24fs device scan + } while(1); + + return foundcount; +} + +void hd24devicenamegenerator::initvars() +{ + imagespath=NULL; + filelist=NULL; + filecount=0; // cache for getnumberoffiles +} + +void hd24devicenamegenerator::clearfilelist() +{ + if (filelist==NULL) + { + return; + } + while (filelist->size()!=0) + { + filelist->pop_back(); + } + delete filelist; + filelist=NULL; +} + +hd24devicenamegenerator::~hd24devicenamegenerator() +{ + clearfilelist(); +} +hd24devicenamegenerator::hd24devicenamegenerator() +{ + initvars(); +} + +const char* hd24devicenamegenerator::imagedir() +{ +#if (DEVGENDEBUG==1) +cout << "hd24devicenamegenerator::imagedir()"<getnumberoffiles(); + __uint32 devcount=this->getnumberofsysdevs(); +#if (DEVGENDEBUG==1) + cout << "return: filecount="<size()==0) + { + return ""; + } + return filelist->at(filenum).c_str(); +} + +#ifdef LINUX +string* hd24devicenamegenerator::getdevicename(__uint32 devicenumber) +{ +#if (DEVGENDEBUG==1) +cout << "hd24devicenamegenerator::getdevicename("<=this->getnumberofsysdevs()) + { + return new string(getfilename(devicenumber-this->getnumberofsysdevs())); + } + string* devname; + __uint32 devgroup = devicenumber; + devicenumber = (devicenumber%26); + devgroup -= devicenumber; + devgroup /= 26; + + switch (devgroup) + { + case 0: + devname = new string("/dev/hd"); + break; + case 1: + devname = new string("/dev/sd"); + break; + default: + return new string(""); + } + + char devletter = (char) ('a' + devicenumber); + *devname += devletter; + + return devname; +} +#endif + +#ifdef WINDOWS + +string* hd24devicenamegenerator::getdevicename(__uint32 devicenumber) +{ +#if (DEVGENDEBUG==1) +cout << "hd24devicenamegenerator::getdevicename("<=this->getnumberofsysdevs()) + { + return new string(getfilename(devicenumber-this->getnumberofsysdevs())); + } + + string* devname = new string("//./PHYSICALDRIVE"); + string* devnum = Convert::int2str(devicenumber); + *devname += *devnum; + delete devnum; + return devname; +} +#endif + +#ifdef DARWIN +string* hd24devicenamegenerator::getdevicename(__uint32 devicenumber) +{ +#if (DEVGENDEBUG==1) +cout << "hd24devicenamegenerator::getdevicename("<=this->getnumberofsysdevs()) + { + return new string(getfilename(devicenumber-this->getnumberofsysdevs())); + } + + string* devname = new string("/dev/disk"); + string* devnum = Convert::int2str(devicenumber); + *devname += *devnum; + delete devnum; + return devname; +} +#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 @@ +#ifndef __hd24devnamegenerator_h__ +#define __hd24devnamegenerator_h__ + +#include +#include +#include +#include +#include +#include "convertlib.h" + +using namespace std; + +class hd24devicenamegenerator +{ + private: + char* imagespath; // path of device images + vector* filelist; + __uint32 getnumberoffiles(); + __uint32 filecount; // cache for getnumberoffiles + __uint32 getnumberofsysdevs(); + __uint32 hd24filecount(const char* imagedir); + void initvars(); + const char* getfilename(__uint32 filenum); + void clearfilelist(); + public: + ~hd24devicenamegenerator(); + hd24devicenamegenerator(); + + __uint32 getnumberofnames(); + string* getdevicename(__uint32 number); + + const char* imagedir(); + + /* + Setting the image dir resets the filecount to 0 + which means the next call will actually count the image + files in the image dir (a rather heavy operation), and + caches the result in filecount. + imagedir(imagedir()) will force a filecount reset. + + If the image dir is NULL, only system devices are returned. + */ + + const char* imagedir(const char* newdir); + /* + returns NULL on alloc error, const char*=dirname otherwise + */ + +}; + +#endif + 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 @@ +#define ALLOC_SECTORS_PER_SONG 5 +#define SONG_SECTORS_PER_SONG 2 +#define TOTAL_SECTORS_PER_SONG (ALLOC_SECTORS_PER_SONG+SONG_SECTORS_PER_SONG) +#ifdef DARWIN +#define creat64 creat +#endif +#define HD24FSDEBUG 0 /* generic hd24fs debugging */ +#define HD24FSDEBUG_QUICKFORMAT 0 /* debugging for calculation of # of free clusters */ +#define HD24FSDEBUG_WRITE 0 /* output debugging messages on disk writes */ +#define HD24FSDEBUG_BITSET 0 /* output debugging messages on disk writes */ +#define HD24FSDEBUG_COMMIT 0 /* output debugging messages on disk writes */ +#define HD24FSDEBUG_DEVSCAN 0 /* output debugging messages for device scan */ +#include "hd24fs.h" +#include +#include +#include +#include +#ifndef WINDOWS +#include +#endif +#define RESULT_SUCCESS 0 +#define RESULT_FAIL 1 +#include +#include +#include +#include +#include +#include "convertlib.h" +#include "memutils.h" + +#include +#define _LARGE_FILES +#define _FILE_OFFSET_BITS 64 +#define FILE_OFFSET_BITS 64 +#define LARGE_FILES +#define LARGEFILE64_SOURCE +#define SECTORSIZE 512 +#ifdef DARWIN +#define open64 open +#define lseek64 lseek +#define pread64 pread +#define pwrite64 pwrite +#endif +#define FSINFO_VERSION_MAJOR 0x8 +#define FSINFO_VERSION_MINOR 0x9 +#define FSINFO_BLOCKSIZE_IN_SECTORS 0x10 +#define FSINFO_AUDIOBLOCKS_PER_CLUSTER 0x14 +#define FSINFO_STARTSECTOR_DRIVEUSAGE 0x38 +#define FSINFO_NUMSECTORS_DRIVEUSAGE 0x3c +#define FSINFO_FREE_CLUSTERS_ON_DISK 0x44 +#define FSINFO_FIRST_PROJECT_SECTOR 0x48 +#define FSINFO_SECTORS_PER_PROJECT 0x4C +#define FSINFO_MAXPROJECTS 0x50 +#define FSINFO_MAXSONGSPERPROJECT 0x54 +#define FSINFO_FIRST_SONG_SECTOR 0x58 +#define FSINFO_SECTORS_IN_SONGENTRY 0x5C +#define FSINFO_SECTORS_IN_SONGALLOC 0x60 +#define FSINFO_SECTORS_PER_SONG 0x64 +#define FSINFO_CURRENT_SONGS_ON_DISK 0x68 +#define FSINFO_ALLOCATABLE_SECTORCOUNT 0x80 +#define FSINFO_LAST_SECTOR 0x84 +#define FSINFO_DATAAREA 0x7c + +#define DRIVEINFO_VOLUME 0x1b8 +#define DRIVEINFO_VOLUME_8 0x00 +#define DRIVEINFO_PROJECTCOUNT 0x0c +#define DRIVEINFO_LASTPROJ 0x10 +#define DRIVEINFO_LASTPROJECT 0x10 +#define DRIVEINFO_PROJECTLIST 0x20 + +#include "hd24project.cpp" +#include "hd24song.cpp" +#if defined(LINUX) || defined(DARWIN) +const int hd24fs::MODE_RDONLY=O_RDONLY; +const int hd24fs::MODE_RDWR=O_RDWR; +#endif +#ifdef WINDOWS +#include +const int hd24fs::MODE_RDONLY=GENERIC_READ; +const int hd24fs::MODE_RDWR=GENERIC_READ|GENERIC_WRITE; +#define popen _popen +#define pclose _pclose +#endif + +const int hd24fs::TRANSPORTSTATUS_STOP =0; +const int hd24fs::TRANSPORTSTATUS_REC =1; +const int hd24fs::TRANSPORTSTATUS_PLAY =2; + +void dumpsector(const char* buffer) +{ + for (int i=0;i<512;i+=16) { + string* dummy=Convert::int32tohex(i); + cout << *dummy << " "; + delete dummy; dummy=NULL; + for (int j=0;j<16;j++) { + string* dummy= Convert::byte2hex(buffer[i+j]); + cout << *dummy; + if (j==7) { + cout << "-" ; + } else { + cout << " " ; + } + delete dummy; dummy=NULL; + } + cout << " "; + for (int j=0;j<16;j++) { + cout << Convert::safebyte(buffer[i+j]); + } + cout << "" << endl; + } +} + +__uint32 hd24fs::songentry2sector(__uint32 songentry) +{ + // Given the possibility to store 99*99 songs, + // converts the song number (0..99*99-1) to + // the sector where the info of that song starts. + // TODO: answer is FSINFO_FIRST_SONG_SECTOR+(FSINFO_SECTORS_PER_SONG*songentry) + // returns 0 when entry number is not legal. + getsector_bootinfo(); + if (sector_boot==NULL) { + // info needed for the calculation is missing. + return 0; + } + __uint32 firstsongsec=Convert::getint32(sector_boot,FSINFO_FIRST_SONG_SECTOR); + __uint32 secspersong=Convert::getint32(sector_boot,FSINFO_SECTORS_PER_SONG); + if (songentry<(99*99)) { + __uint32 secnum=(firstsongsec+(songentry*secspersong)); + return secnum; + } + return 0; // entry number is not legal. +} + +__uint32 hd24fs::songsondisk() +{ + getsector_bootinfo(); + if (sector_boot==NULL) { + // info needed for the calculation is missing. + return 0; + } + return Convert::getint32(sector_boot,FSINFO_CURRENT_SONGS_ON_DISK); +} + +void hd24fs::songsondisk(__uint32 songcount) +{ + getsector_bootinfo(); + if (sector_boot==NULL) { + // info needed for the calculation is missing. + return; //cannot update. + } + Convert::setint32(sector_boot,FSINFO_CURRENT_SONGS_ON_DISK,songcount); +} + +__uint32 hd24fs::songsector2entry(__uint32 songsector) +{ + // given the sector where a song entry starts, + // returns the entry number of that song. + // Entry number typically ranges from 0 + // to (99*99)-1. + // A value 0xffffffff is returned when the + // sector number is not valid. + getsector_bootinfo(); + if (sector_boot==NULL) { + // info needed for the calculation is missing. + return 0xFFFFFFFF; // sector number is not valid. + } + __uint32 firstsongsec=Convert::getint32(sector_boot,FSINFO_FIRST_SONG_SECTOR); + __uint32 secspersong=Convert::getint32(sector_boot,FSINFO_SECTORS_PER_SONG); + __uint32 offset=songsector-firstsongsec; + if ((offset%secspersong) !=0) { + return 0xFFFFFFFF; // sector number is not valid. + } + __uint32 resultentry=(offset/secspersong); + if (resultentry>=(99*99)) return 0xFFFFFFFF; + return resultentry; +} + +__uint32 hd24fs::cluster2sector(__uint32 clusternum) +{ + getsector_bootinfo(); + if (sector_boot==NULL) { + // unknown cluster size. + return 0; + } + return Convert::getint32(sector_boot,FSINFO_DATAAREA) /* first audio sector */ + +( + Convert::getint32(sector_boot,FSINFO_BLOCKSIZE_IN_SECTORS) + * Convert::getint32(sector_boot,FSINFO_AUDIOBLOCKS_PER_CLUSTER) + * clusternum + ); +} + +__uint32 hd24fs::sector2cluster(__uint32 sectornum) +{ + getsector_bootinfo(); + if (sector_boot==NULL) { + // unknown cluster size. Return 'undefined' cluster number. + return CLUSTER_UNDEFINED; + } + __uint32 dataarea=Convert::getint32(sector_boot,FSINFO_DATAAREA); + + if (sectornum0. Wrap around. + nextfreeclusterword=0; + return getnextfreeclusterword(); + } + } + // we found a (set of 32) free cluster(s). + nextfreeclusterword=i; + return (i*32); +} + +unsigned long hd24fs::getlastsectornum() +{ +#if (HD24FSDEBUG==1) + cout <<"hd24fs::getlastsectornum()" << endl; +#endif + // cache result. + if (gotlastsectornum==false) { + foundlastsectornum=getlastsectornum(devhd24); + gotlastsectornum=true; + } + return foundlastsectornum; +} + +void hd24fs::setwavefixmode(int mode) +{ + wavefixmode=mode; +} + +void hd24fs::setmaintenancemode(int mode) +{ + maintenancemode=mode; +} + +int hd24fs::getmaintenancemode() +{ + return maintenancemode; +} + +string* hd24fs::getdevicename() { + + return this->devicename; +} + +void hd24fs::setdevicename(const char* orig,string* devname) +{ + if (this->devicename!=NULL) { + delete this->devicename; + this->devicename=NULL; + } + this->devicename=new string(devname->c_str()); +} + +unsigned long hd24fs::getlastsectornum(FSHANDLE handle) +{ +#if (HD24FSDEBUG==1) + cout <<"hd24fs::getlastsectornum(FSHANDLE handle)" << endl; +#endif +#if defined(LINUX) || defined(DARWIN) + __uint64 curroff=lseek64(handle,0,SEEK_CUR); + __uint64 sectors=(lseek64(handle,0,SEEK_END)+1)>>9; + lseek64(handle,curroff,SEEK_SET); + return sectors-1; +#endif + /* unfortunately, apart from other functions being needed + * to read 64 bit files, the elegant solution above won't + * work on Windows, because it is not possible to + * request the file size of a device. + */ + +#ifdef WINDOWS + unsigned char buffer[2048]; + LARGE_INTEGER lizero; + lizero.QuadPart=0; + LARGE_INTEGER saveoff; + LARGE_INTEGER filelen; + filelen.QuadPart=0; + SetFilePointerEx(handle,lizero,&saveoff,FILE_CURRENT); // save offset + /* If things would work properly, the following would + * not only work for regular files, but also for devices. + * Perhaps the next version of Windows has proper hardware + * abstraction and this will magically start working. + */ + if (0!=SetFilePointerEx(handle,lizero,&filelen,FILE_END)) { + SetFilePointerEx(handle,saveoff,NULL,FILE_BEGIN); // restore offset + return ((filelen.QuadPart)/512); + } + SetFilePointerEx(handle,saveoff,NULL,FILE_BEGIN); // restore offset +#if (HD24FSDEBUG==1) + cout << "fileptr method failed" << endl; +#endif + /* The proper way to do things has failed (probably because + * we are dealing with a device file instead of with a + * regular one. + */ + + /* TODO: Before trying a raw sectornum scan, + we can still check if we're dealing with a valid + superblock, not using a headerfile and checking if + the last sector as indicated by the superblock points + to a copy of that superblock. This won't work on a raw + drive, of course, but will provide a reasonably safe + workaround for valid HD24 drives. */ + + /* The workaround has also failed, so we need to perform + raw drive size detection. Windows does not have a reliable + way to get the real LBA sector count, so we need to perform + the following semi-smart trick (if you have a better idea that + works on all windows versions and all drive types, + I'd be thrilled to know!) + + - First, iterate reading sector numbers until it fails. + To keep speed acceptable, multiply sector number by 2 + each time. + - After failed read, do a binary search between the + failed read sector number and the sector number of + the last successful read. + - As the drive MUST be aware of its own size, this will + give the real sector count of the drive. + */ + lizero.QuadPart=0; + saveoff.QuadPart=0; + + LARGE_INTEGER maxbytes; + maxbytes.QuadPart=0; + SetFilePointerEx(handle,lizero,&saveoff,FILE_CURRENT); // save offset + + long bytesread=1; + unsigned long trysector=1; + unsigned long oldtrysector=1; + int drivetoosmall=1; + bytesread=readsectors(handle,trysector,buffer,1); // raw/audio read (no fstfix needed) + unsigned long lastok=0; + unsigned long firstfail=0; + //int dummy; + /* This loop doubles the sector number. Actually stays at 2^n-1, + * this will likely perform better than 2^n because chances are + * greater that it stays below disk boundaries, preventing slow + * timeouts. + */ + while (bytesread>0) + { +#if (HD24FSDEBUG==1) + cout << "trysector=" << trysector << endl; +#endif +// cin >> dummy; + drivetoosmall=0; + oldtrysector=trysector; + trysector=trysector*2+1; // count will be 1,3,7,15,31,... =(2^n)-1 + if (oldtrysector==trysector) + { + // x*2+1 yields x - this means all + // bits are turned on and we overflow. + // So we're at 4 tera limit. + // 4 terabyte and still nothing found? hmmmm + SetFilePointerEx(handle,saveoff,NULL,FILE_BEGIN); + return 0; + } + bytesread=0; + bytesread=readsectors(handle,trysector,buffer,1); // raw/audio read (no fstfix needed) +#if (HD24FSDEBUG==1) + cout << " bytesread=" <0) { + lastok=trysector; + } else { + firstfail=trysector; + } + } + /* We have the sector number of the last successful read and + * of the failed read. Time to do a binary search. */ + unsigned long lowerbound=lastok; +#if (HD24FSDEBUG==1) + cout << "lastok=" << lastok << endl; + cout << "firstfaiL=" << firstfail << endl; + +#endif + if (lastok==0) + { + if (firstfail==0) + { + return 0; + } + } + unsigned long upperbound=lastok*2; + unsigned long midpos=0; + while (lowerbound<=upperbound) + { + //midpos=lowerbound+floor((upperbound-lowerbound)/2); + midpos=lowerbound+(__uint32)floor((upperbound-lowerbound)/8); + // prefer asymmetrical search due to time out when + // searching past upperbound +// cout << "try=" << midpos << endl; + bytesread=readsectors(handle,midpos,buffer,1); // raw/audio read (no fstfix needed) + if (bytesread>0) { + lowerbound=midpos+1; + } else { + // could not read midpos, + // so upperbound is before that. + upperbound=midpos-1; + } + } + if (midpos==lowerbound) + { + midpos--; + } + /* midpos is now last sector number. counting starts at sector 0 + * so total number of sectors is one more. */ + midpos++; + SetFilePointerEx(handle,saveoff,&saveoff,FILE_BEGIN); //restore + + __uint64 sectors=midpos; +// cout << "found " <songsondisk(); +} + +__uint32 hd24raw::getlastsectornum() +{ + return fsys->getlastsectornum(); +} + +__uint32 hd24raw::getprojectsectornum(__uint32 x) +{ + return fsys->getprojectsectornum(x); +} + +__uint32 hd24raw::quickformat(char* message) +{ + return fsys->quickformat(message); +} + +unsigned long hd24raw::getnextfreesector(__uint32 cluster) +{ + return fsys->getnextfreesector(cluster); +} + +hd24raw::hd24raw(hd24fs* p_fsys) +{ + fsys=p_fsys; +} + +long hd24raw::readsectors(unsigned long secnum, unsigned char* buffer,int sectors) +{ + return fsys->readsectors(fsys->devhd24, secnum, buffer,sectors); +} + +long hd24raw::writesectors(unsigned long secnum, unsigned char* buffer,int sectors) +{ + return fsys->writesectors(fsys->devhd24, secnum, buffer,sectors); +}; + +bool hd24fs::isinvalidhandle(FSHANDLE handle) +{ +#ifdef WINDOWS + if (handle==FSHANDLE_INVALID) { + return true; + } +#endif +#if defined(LINUX) || defined(DARWIN) + if (handle==0) { + return true; + } + if (handle==FSHANDLE_INVALID) { + return true; + } +#endif + return false; +} + +bool hd24fs::isexistingdevice(string* devname) +{ +#if defined(LINUX) || defined(DARWIN) +#if (HD24FSDEBUG==1) +cout << "try open device " << devname->c_str() << endl; +#endif + FSHANDLE handle=open64(devname->c_str(),MODE_RDONLY); //read binary +#endif +#ifdef WINDOWS + FSHANDLE handle=CreateFile(devname->c_str(),MODE_RDONLY, + FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); +#endif + if (!isinvalidhandle(handle)) return true; + return false; +} + +FSHANDLE hd24fs::findhd24device(int mode,string* devname,bool force,bool tryharder) +{ +#if (HD24FSDEBUG_DEVSCAN==1) + cout << "FSHANDLE hd24fs::findhd24device(" << mode << ", " << *devname << ", force=" << force << ",tryharder=" << tryharder <<")" << endl; +#endif + unsigned char findhdbuf[1024]; + unsigned char compare1buf[1024]; + unsigned char compare2buf[1024]; +#if defined(LINUX) + FSHANDLE handle=open64(devname->c_str(),mode,0); //read binary +#endif +#if defined(DARWIN) + FSHANDLE handle=open64(devname->c_str(),mode); //read binary +#endif +#ifdef WINDOWS +#if (HD24FSDEBUG_DEVSCAN==1) + cout << "Mode=" << mode << endl; +#endif + FSHANDLE handle=CreateFile(devname->c_str(),mode, + FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); +#endif + + if (isinvalidhandle(handle)) { + if (mode==MODE_RDWR) + { + // attempt fallback to read-only mode + // (for CDROM/DVD devices etc) + mode=MODE_RDONLY; +#if defined(LINUX) || defined(DARWIN) + handle=open64(devname->c_str(),mode); //read binary +#endif +#ifdef WINDOWS +#if (HD24FSDEBUG==1) +// cout << "Mode=" << mode << endl; +#endif + handle=CreateFile(devname->c_str(),mode, + FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); +#endif + + } + + + } + + if (isinvalidhandle(handle)) { + return handle; + } + + // can open device. + __uint32 sectornum=0; + if (tryharder) { + sectornum=getlastsectornum(handle); + } + + readsector_noheader(handle,sectornum,findhdbuf); // fstfix follows + fstfix(findhdbuf,512); + string* fstype=Convert::readstring(findhdbuf,0,8); + bool isadat=false; + + if (*fstype=="ADAT FST") { + /* Okay, but if we are 'trying harder' we can run into + a false positive for old HD24 drives that are now in + use as OS drive. So we'll demand that the second and + secondlast sector are equal. + */ + if (tryharder) + { + readsector_noheader(handle,sectornum-1,compare1buf); + readsector_noheader(handle,1,compare2buf); + if (memcmp(compare1buf,compare2buf,512)==0) + { + isadat=true; + } + else + { + /* Drive may have been an ADAT drive, + but no longer is. If it is in fact an + ADAT drive but corrupted, it is still + possible to force detection using force + mode. Give it another chance; do not + enable write prevention for now. + */ + isadat=false; + } + } + else + { + isadat=true; + } + } + delete fstype; + + if (isadat) return handle; + + if (force) + { + forcemode=true; + m_isOpen=true; + this->writeprotected=true; // TODO: unless expert mode is enabled too. May also be overridden to allow formatting. + return handle; + } + hd24closedevice(handle); + return FSHANDLE_INVALID; +} + +unsigned long hd24fs::hd24devicecount() +{ + /* Attempt to auto-detect a hd24 disk on all IDE and SCSI devices. + (this should include USB and firewire) */ + FSHANDLE handle; + int devcount=0; +#if (HD24FSDEBUG==1) + cout << "====PERFORMING DEVICE COUNT====" << endl; +#endif + hd24devicenamegenerator* dng=new hd24devicenamegenerator(); + dng->imagedir(this->imagedir); + + __uint32 totnames=dng->getnumberofnames(); +// cout << totnames << " devices" << endl; + for (__uint32 j=0;j<2;j++) + { + // 2 loops: one to try, one to try harder + // first loop searches strictly valid devices + // second loop searches for possibly corrupted devices + bool tryharder=false; + if (j==1) { + tryharder=true; + } + for (__uint32 i=0;igetdevicename(i); + handle=findhd24device(MODE_RDONLY,devname,false,tryharder); +#if (HD24FSDEBUG_DEVSCAN==1) + cout << "try device no " <0) { + break; + } + } +#if (HD24FSDEBUG==1) + cout << "====END OF DEVICE COUNT, " << devcount << " DEVICES FOUND ====" << endl; +#endif + delete (dng); + return devcount; +} + +void hd24fs::setimagedir(const char* newdir) +{ +#if (HD24FSDEBUG==1) +if (newdir==NULL) +{ + cout << "hd24fs::setimagedir(NULL)"<< endl; +} +else +{ + cout << "hd24fs::setimagedir("<imagedir!=NULL) + { + free ((void*)imagedir); + this->imagedir=NULL; + } + + if (newdir!=NULL) + { + this->imagedir=(char*)malloc(strlen(newdir)+1); + if (this->imagedir!=NULL) + { + strncpy((char*)imagedir,newdir,strlen(newdir)+1); + } + } + + return; //return (const char*)imagedir; +} + +FSHANDLE hd24fs::findhd24device(int mode,int base0devnum) +{ +#if (HD24FSDEBUG_DEVSCAN==1) + cout << "hd24fs::findhd24device(" << mode << "," << base0devnum << ")" << endl; +#endif + // TODO: Reduce code duplication in this subroutine + // and hd24devicecount + /* Attempt to auto-detect a hd24 disk on all known + IDE and SCSI devices. (this should include USB + and firewire) */ + int currdev=0; + FSHANDLE handle; + hd24devicenamegenerator* dng=new hd24devicenamegenerator(); + dng->imagedir(this->imagedir); + + __uint32 totnames=dng->getnumberofnames(); +#if (HD24FSDEBUG==1) + cout << totnames << " devices" << endl; +#endif + for (__uint32 j=0;j<2;j++) + { + // 2 loops: one to try, one to try harder + // first loop searches strictly valid devices + // second loop searches for possibly corrupted devices + + bool tryharder=false; + if (j==1) { + tryharder=true; + } + + for (__uint32 i=0;igetdevicename(i); + handle=findhd24device(mode,devname,false,tryharder); + + if (!(isinvalidhandle(handle))) { + if (currdev==base0devnum) { + // String "3" indicates origin, i.e. + // who is setting the device name. + // Useful for debugging purposes. + setdevicename("3",devname); + deviceid=i; + p_mode=mode; + delete (devname); + delete (dng); + return handle; + } + hd24closedevice(handle); + currdev++; + } + delete (devname); + } + } + delete (dng); + return FSHANDLE_INVALID; +} + +void hd24fs::hd24closedevice(FSHANDLE handle) { +#if defined(LINUX) || defined(DARWIN) + close(handle); +#endif +#ifdef WINDOWS + CloseHandle(handle); +#endif +} + +FSHANDLE hd24fs::findhd24device(int mode) +{ + /* Attempt to auto-detect a hd24 disk on all IDE and SCSI devices. + (this should include USB and firewire) */ + return findhd24device(mode,0); +} + +FSHANDLE hd24fs::findhd24device() +{ + return findhd24device(MODE_RDONLY); +} + +int hd24fs::gettransportstatus() +{ + return this->transportstatus; +} + +void hd24fs::settransportstatus(int newstatus) +{ + this->transportstatus=newstatus; +} + +int hd24fs::getdeviceid() +{ + return deviceid; +} + +void hd24fs::initvars() +{ + this->deviceid=-1; + this->writeprotected=false; // by default allow writes. + // can be disabled if corrupt + // state is detected. + this->transportstatus=TRANSPORTSTATUS_STOP; + this->imagedir=NULL; + this->nextfreeclusterword=0; + this->gotlastsectornum=false; + this->foundlastsectornum=0; + this->forcemode=false; + this->headersectors=0; + sector_boot=NULL; + sector_diskinfo=NULL; + sectors_driveusage=NULL; + sectors_orphan=NULL; + sectors_songusage=NULL; + projlist=NULL; + this->m_isOpen=false; + this->allinput=false; + this->autoinput=false; + this->wavefixmode=false; + this->formatting=false; + this->maintenancemode=false; + this->headermode=false; + this->devicename=NULL; + this->highestFSsectorwritten=0; + // 0x10c76 is last sector of song/project area (without undo buffer) + return; +} + +hd24fs::hd24fs(const char* imagedir,int mode) +{ + initvars(); + setimagedir(imagedir); + devicename=new string(""); + devhd24=findhd24device(mode); + if (!(isinvalidhandle(devhd24))) { + m_isOpen=true; + p_mode=mode; + } + return; +} + +hd24fs::hd24fs(const char* imagedir,int mode,int base0devnum) +{ +#if (HD24FSDEBUG==1) + cout << "hd24fs::hd24fs(" << mode << "," << base0devnum << ")" << endl; +#endif + initvars(); + setimagedir(imagedir); + devicename=new string(""); + devhd24=findhd24device(mode,base0devnum); + if (!(isinvalidhandle(devhd24))) { + m_isOpen=true; + p_mode=mode; + } + return; +} + +hd24fs::hd24fs(const char* imagedir,int mode,string* devname,bool force) +{ + initvars(); + setimagedir(imagedir); + devicename=new string(devname->c_str()); + bool tryharder=false; + devhd24=findhd24device(mode,devname,force,tryharder); + if (!(isinvalidhandle(devhd24))) { + m_isOpen=true; + p_mode=mode; + } + return; +} + +hd24fs::hd24fs(const char* imagedir) +{ + initvars(); + setimagedir(imagedir); + devicename=new string(""); + devhd24=findhd24device(MODE_RDONLY); + if (!(isinvalidhandle(devhd24))) { + m_isOpen=true; + p_mode=MODE_RDONLY; + } + return; +} + +hd24fs::~hd24fs() +{ +#if (HD24FSDEBUG==1) + cout << "Deleting devicename" << endl; +#endif + if (devicename!=NULL) { + delete devicename; + devicename=NULL; + } +#if (HD24FSDEBUG==1) + cout << "Close FS handle" << endl; +#endif + if (isOpen()) + { + hd24close(); + } +#if (HD24FSDEBUG==1) + cout << "Free superblock mem" << endl; +#endif + if (sector_boot!=NULL) + { + memutils::myfree("sectors_boot",sector_boot); + sector_boot=NULL; + } +#if (HD24FSDEBUG==1) + cout << "Free diskinfo mem" << endl; +#endif + if (sector_diskinfo!=NULL) + { + memutils::myfree("sectors_diskinfo",sector_diskinfo); + sector_diskinfo=NULL; + } +#if (HD24FSDEBUG==1) + cout << "Free drive usage mem" << endl; +#endif + if (sectors_driveusage!=NULL) + { + memutils::myfree("sectors_driveusage",sectors_driveusage); + sectors_driveusage=NULL; + } +#if (HD24FSDEBUG==1) + cout << "Free orphan sectors mem" << endl; +#endif + if (sectors_orphan!=NULL) + { + memutils::myfree("sectors_orphan",sectors_orphan); + sectors_orphan=NULL; + } +#if (HD24FSDEBUG==1) + cout << "Free song usage sectors mem" << endl; +#endif + if (sectors_songusage!=NULL) + { + memutils::myfree("sectors_songusage",sectors_songusage); + sectors_songusage=NULL; + }; + // commit? +} + +bool hd24fs::isOpen() +{ + if (this->m_isOpen) + { + return true; + } + return false; +} + +void hd24fs::hd24close() +{ + // TODO: At the point that we start supporting + // write access, we will need to flush and close + // the device here. + + hd24closedevice(this->devhd24); +} + +void hd24fs::fstfix(unsigned char * bootblock,int fixsize) +{ + if (bootblock==NULL) return; + if (fixsize<=0) return; +#if (HD24FSDEBUG==1) + cout << "fstfix("<>32; + li.LowPart=seekpos%((__uint64)1<<32); +//LowPart=seekpos% +// SetFilePointer(devhd24,seekpos,NULL,FILE_BEGIN); + SetFilePointerEx(devhd24,li,NULL,FILE_BEGIN); + // TODO: SetFilePointer vs SetFilePointerEx + // DWORD SetFilePointer( + // HANDLE hFile, + // LONG lDistanceToMove, + // PLONG lpDistanceToMoveHigh, + // DWORD dwMoveMethod + // ); + // + // vs. + // BOOL SetFilePointerEx( + // HANDLE hFile, + // LARGE_INTEGER liDistanceToMove, + // PLARGE_INTEGER lpNewFilePointer, + // DWORD dwMoveMethod + // ); + // +#endif + return; +} + +long hd24fs::writesectors(FSHANDLE devhd24,unsigned long sectornum,unsigned char * buffer,int sectors) +{ + ////// + // this bit keeps track of the highest FS sector written + // to keep commit times acceptable: commit function will then + // only backup up to the highest sector used. + // (this is still suboptimal performance-wise but requires + // a minimum of memory and administration during writes). + __uint32 lastsec=sectornum+(sectors-1); + if (lastsec<=0x10c76) + { + // 0x10c76 is last sector of song/project area (without + // undo buffer). TODO: calculate based on superblock. info. + if (lastsec>highestFSsectorwritten) + { + highestFSsectorwritten=lastsec; + } + } + ////// + +#if (HD24FSDEBUG_WRITE==1) + cout << " writesectors sectornum " << sectornum << ", sectorcount=" << sectors << endl; +#endif + if (this!=NULL) + { + if (this->writeprotected) + { +#if (HD24FSDEBUG_WRITE==1) + cout << "Write protected- not writing. " << endl; +#endif + return 0; + } + } + FSHANDLE currdevice=devhd24; + +#if (HD24FSDEBUG_WRITE==1) + cout << "WRITESECTORS sec=" << sectornum << " buf=" << buffer << "#=" << sectors << endl; +#endif + int WRITESIZE=SECTORSIZE*sectors; // allows searching across sector boundaries + +// cout << "headersectors=" << this->headersectors << "this=" <headersectors)!=0) + { +// cout << "headermode enabled." << endl; + // Header mode is active. Only allow writing over header area. + if (sectornumheadersectors) + { +// cout << "Headermode enabled for sector " << sectornum << endl; + currdevice=hd24header; + + } else { + // headermode is active yet caller is trying to write over drive + // data area. We cannot allow this (for safety reasons). + return 0; + +// cout << "Headermode disabled for sector " << sectornum << endl; + } + } else { +// cout << "Headermode disabled. " << sectornum << endl; + } + } + + hd24seek(currdevice,(__uint64)sectornum*512); + +#if defined(LINUX) || defined(DARWIN) || defined(__APPLE__) + long bytes=pwrite64(currdevice,buffer,WRITESIZE,(__uint64)sectornum*512); //1,devhd24); +// cout << "BYTES=" << bytes << endl; +#endif +#ifdef WINDOWS + DWORD dummy; + long bytes=0; + if (WriteFile(currdevice,buffer,WRITESIZE,&dummy,NULL)) { + bytes=WRITESIZE; + }; +#endif + return bytes; +} + +long hd24fs::readsectors(FSHANDLE devhd24,unsigned long sectornum,unsigned char * buffer,int sectors) +{ + FSHANDLE currdevice=devhd24; + // The following prints the sector num in hex: +#if (HD24FSDEBUG==1) +/* string* x=this->p_convert->int32tohex(sectornum); + cout << *x << endl; + delete x; +*/ +#endif + +// cout << "headersectors=" << this->headersectors << "this=" <headersectors)!=0) + { +// cout << "headermode enabled." << endl; + if (sectornumheadersectors) + { +// cout << "Headermode enabled for sector " << sectornum << endl; + currdevice=hd24header; + } else { +// cout << "Headermode disabled for sector " << sectornum << endl; + } + } else { +// cout << "Headermode disabled. " << sectornum << endl; + } + hd24seek(currdevice,(__uint64)sectornum*SECTORSIZE); + int READSIZE=SECTORSIZE*(sectors); +#if defined(LINUX) || defined(DARWIN) + long bytes_read=pread64(currdevice,buffer,READSIZE,(__uint64)sectornum*512); //1,currdevice); +#endif +#ifdef WINDOWS +// cout << "Readsectors: num="<devhd24,sectornum,bootblock); +} + +long hd24fs::readsector_noheader(FSHANDLE devhd24,unsigned long sectornum,unsigned char * bootblock) +{ + unsigned long headersecs=this->headersectors; + this->headersectors=0; // disable header processing, if applies + long number_read=readsectors(devhd24,sectornum,bootblock,1); + this->headersectors=headersecs; // re-enable header processing + return number_read; +} + +long hd24fs::writesector(FSHANDLE devhd24,unsigned long sectornum,unsigned char * bootblock) +{ + return writesectors(devhd24,sectornum,bootblock,1); +} + +string* hd24fs::gethd24currentdir(int argc,char* argv[]) +{ + /* For future use. We may save a file in the + homedir of the user containing info about which + "path" (project/songname/file format) was last + selected by the user. + */ + + return new string("/"); +} + +string* hd24fs::gethd24currentdir() +{ + return new string("/"); +} + +unsigned char* hd24fs::readdiskinfo() +{ +#if (HD24FSDEBUG==1) + cout << "Driveusage before readdiskinfo=" << (int)(this->sectors_driveusage) << endl; +#endif + // read disk info + if (/*formatting||*/(sector_boot==NULL)) + { + this->readbootinfo(); + } + if (sector_diskinfo!=NULL) + { + memutils::myfree("readdiskinfo",sector_diskinfo); + sector_diskinfo=NULL; + } + sector_diskinfo=(unsigned char *)memutils::mymalloc("readdiskinfo",1024,1); + if (sector_diskinfo!=NULL) + { + readsector(devhd24,1,sector_diskinfo); // fstfix follows + fstfix (sector_diskinfo,512); + } +#if (HD24FSDEBUG==1) + cout << "Driveusage after readdiskinfo=" << (int)(this->sectors_driveusage) << endl; +#endif + return sector_diskinfo; +} + +bool hd24fs::useheaderfile(string headerfilename) +{ + getsector_bootinfo(); + if (sector_boot==NULL) + { + /* we haven't got a main device yet + so we cannot apply a header to it */ + return false; + } + // allow writing to header. +#if defined(LINUX) || defined(DARWIN) + FSHANDLE handle=open64(headerfilename.c_str(),MODE_RDWR); //read binary +#endif +#ifdef WINDOWS +// cout << "Mode=" << mode << endl; + FSHANDLE handle=CreateFile(headerfilename.c_str(),MODE_RDWR, + FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); +#endif + + if (isinvalidhandle(handle)) return false; +// cout << "Trying to enable header mode with file " << headerfilename << endl; + hd24header=handle; + this->headersectors=0; + this->headersectors=getlastsectornum(hd24header)+1; + // re-read disk info as number of projects etc can differ with header + readsector(devhd24,1,sector_diskinfo); // fstfix follows + fstfix (sector_diskinfo,512); + +// cout << "headersectors=" << this->headersectors << "this=" <setname(buffer,drivename,DRIVEINFO_VOLUME_8,DRIVEINFO_VOLUME); + return; +} + +void hd24fs::useinternalboot(unsigned char* buffer,__uint32 lastsector) +{ + unsigned char internal_boot[136]= + { + 0x54,0x41,0x44,0x41,0x54,0x53,0x46,0x20, 0x20,0x30,0x31,0x31,0x33,0xcc,0xaa,0x55, + 0x80,0x04,0x00,0x00,0x02,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x01,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x02,0x00,0x00,0x00,0x03,0x00,0x00,0x00, 0x05,0x00,0x00,0x00,0x0f,0x00,0x00,0x00, + 0x2f,0x04,0x00,0x00,0x00,0x00,0x00,0x00, 0x14,0x00,0x00,0x00,0x01,0x00,0x00,0x00, + 0x63,0x00,0x00,0x00,0x63,0x00,0x00,0x00, 0x77,0x00,0x00,0x00,0x02,0x00,0x00,0x00, + 0x05,0x00,0x00,0x00,0x07,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x49,0x26,0x00,0x00, + 0x76,0x0c,0x01,0x00,0x80,0x8b,0x12,0x00, 0x1f,0x04,0x00,0x00,0xf6,0x97,0x13,0x00, + 0x14,0x89,0xb4,0x04,0x7f,0x2d,0xc9,0x04 + }; + + clearbuffer(buffer); + + /* fill buffer with default boot info */ + for (unsigned int i=0;imaxprojects(); + __uint32 maxsongcount=this->maxsongsperproject(); + __uint32 totentries=maxprojs*maxsongcount; // 99 songs, 99 projects +#if (HD24FSDEBUG==1) + cout << "Clear song usage table..."<< endl; + cout << "this=" << this << endl; +#endif + for (i=0;isectors_driveusage==NULL) + { + unsigned char* du=(unsigned char *)memutils::mymalloc("resetdriveusage/sectors_driveusage",512*15,1); + sectors_driveusage=du; + if (this->sectors_driveusage==NULL) + { + return NULL; + } + } + + for (int i=0;i<512*15;i++) + { + sectors_driveusage[i]=0xff; + } + + if (formatting||(sector_boot==NULL) ) + { +#if (HD24FSDEBUG_QUICKFORMAT==1) + cout << "hd24fs::resetdriveusage() - reloading boot info " << endl; +#endif + + this->readbootinfo(); + } else { +#if (HD24FSDEBUG_QUICKFORMAT==1) + cout << "hd24fs::resetdriveusage() - using current (not reloading) boot info " << endl; +#endif + + } + + __uint32 i; + // table is initialized, now populate it. + __uint32 totentries=Convert::getint32(sector_boot,FSINFO_FREE_CLUSTERS_ON_DISK); +#if (HD24FSDEBUG_QUICKFORMAT==1) + cout << "According to superblock, free clusters on disk=" << totentries << endl; + dumpsector((const char*)sector_boot); +#endif +#if (HD24FSDEBUG_QUICKFORMAT==1) + cout << "before reset, drive usage looks as follows: "<< endl; + dumpsector((const char*)sectors_driveusage); +#endif + for (i=0;isongcount(); + for (j=1; j<=currsongcount;j++) + { + // get song sector info. + __uint32 songsector = currproj->getsongsectornum(j); + if (songsector==0) + { + // song at given entry is not in use + // in this project, no need to mark it as used. + continue; + } + + // mark the song used based on its entry number + // (calculated from the sector where it lives) + __uint32 songentry=songsector2entry(songsector); + if (songentry!=INVALID_SONGENTRY) + { + enablebit(songentry,sectors_songusage); + } + } + + if (currproj!=NULL) + { + delete(currproj); + currproj=NULL; + } + } + return sectors_songusage; +} + +void hd24fs::refreshsongusage() +{ + unsigned char* songusage=calcsongusage(); + __uint32 sectornum=2; /* TODO: get from fs */ + __uint32 sectorcount=3; /* TODO: get from fs */ + fstfix(songusage,sectorcount*512); + setsectorchecksum(songusage, + 0 /* startoffset */, + sectornum /* sector */, + sectorcount /*sectorcount */ + ); + this->writesectors(this->devhd24, + sectornum, + songusage, + sectorcount); + fstfix(songusage,sectorcount*512); + + /* this also implies we need to update the superblock + with the current song count */ + __uint32 songcount=0; + for (int i=0;i<99*99;i++) { + if (!(isbitzero(i,songusage))) + { + songcount++; + } + }; + songsondisk(songcount); + fstfix(sector_boot,512); + setsectorchecksum(sector_boot, + 0 /* startoffset */, + 0 /* sector */, + 1 /*sectorcount */); + this->writesectors(this->devhd24, + 0, + sector_boot, + 1); + fstfix(sector_boot,512); + return; +} + +unsigned char* hd24fs::getsector_diskinfo() +{ + getsector_bootinfo(); + unsigned char* targetbuf=sector_diskinfo; + if (/*formatting||*/(sector_diskinfo==NULL) ) + { + targetbuf=readdiskinfo(); + } + return sector_diskinfo; +} + +unsigned char* hd24fs::getsector_bootinfo() +{ + unsigned char* targetbuf=sector_boot; + if (/*formatting||*/(sector_boot==NULL) ) + { +#if (HD24FSDEBUG_QUICKFORMAT==1) + cout << "Re-reading bootinfo now." << endl; +#endif + targetbuf=readbootinfo(); + } + return targetbuf; +} + +unsigned char* hd24fs::getsectors_driveusage() +{ +#if (HD24FSDEBUG_QUICKFORMAT==1) + cout << "hd24fs::getsectors_driveusage()" << endl; +#endif + + readbootinfo(); + if (sectors_driveusage==NULL) + { + sectors_driveusage=readdriveusageinfo(); + } + return sectors_driveusage; +} + +unsigned char* hd24fs::getcopyofusagetable() +{ + unsigned char* copyusagetable=(unsigned char*)memutils::mymalloc("copyusagetable",15*512,1); + if (copyusagetable==NULL) + { + /* Out of memory */ + return NULL; + } + + // copy current drive usage table to a copy; + readdriveusageinfo(); + int i; + for (i=0;i<(512*15);i++) { + copyusagetable[i]=sectors_driveusage[i]; + } + return copyusagetable; +} + +string* hd24fs::volumename() +{ + if (!(isOpen())) + { + return new string(""); + } + getsector_diskinfo(); + return Convert::readstring(sector_diskinfo,DRIVEINFO_VOLUME,64); +} + +void hd24fs::setvolumename(string newname) +{ + if (sector_diskinfo==NULL) + { + readdiskinfo(); + } + this->setname(sector_diskinfo,newname,DRIVEINFO_VOLUME_8,DRIVEINFO_VOLUME); + return; +} + +unsigned long hd24fs::driveusagesectorcount() +{ + if (!(isOpen())) + { + cout << "FS not open!"; + return 0; + } +#if (HD24FSDEBUG_QUICKFORMAT==1) + cout << "Figuring out number of sectors used for drive usage" + << endl; +#endif + + getsector_bootinfo(); + return Convert::getint32(sector_boot,FSINFO_NUMSECTORS_DRIVEUSAGE); +} + +unsigned long hd24fs::clustercount() +{ + /* + Clustercount= + (number of allocatable sectors on disk)/ + ((sectors per audioblock)*(audioblocks per cluster)) + */ + if (!(isOpen())) + { + return 0; + } + getsector_bootinfo(); + __uint32 allocatablesectorcount= + Convert::getint32(sector_boot,FSINFO_ALLOCATABLE_SECTORCOUNT); + __uint32 audioblocksize= + Convert::getint32(sector_boot,FSINFO_BLOCKSIZE_IN_SECTORS); + __uint32 clustersize= + Convert::getint32(sector_boot,FSINFO_AUDIOBLOCKS_PER_CLUSTER) + *audioblocksize; + + allocatablesectorcount-=(allocatablesectorcount%clustersize); + return allocatablesectorcount/clustersize; +} + +void hd24fs::dumpclusterusage(unsigned char* usagebuffer) +{ + if (!(isOpen())) + { + return; + } + __uint32 clusters=clustercount(); + for (__uint32 i=0;igetproject(proj); + int numsongs=currproj->songcount(); + for (int song=1; song<=numsongs; song++) { + hd24song* currsong=currproj->getsong(song); + if (currsong==NULL) continue; + currsong->unmark_used_clusters(sectors_orphan); + delete currsong; + } + if (currproj!=NULL) { + delete currproj; + currproj=NULL; + } + } + return sectors_orphan; +} + +bool hd24fs::isbitzero(unsigned long i,unsigned char* usagebuffer) +{ + int bitnum=i%32; + i-=bitnum; + i/=32; // i now is word num + i*=4; // i now is offset + __uint32 getword=Convert::getint32(usagebuffer,i); + __uint32 mask=1; +#if (HD24FSDEBUG_BITSET==1) + cout << "bitnum=" << bitnum << " "; +#endif + mask=mask<0xFF) return 0; +#if (HD24FSDEBUG_QUICKFORMAT==1) + cout << "Sectors used for drive usage=" << fsc << endl; +#endif + __uint32 clusters=((fsc /*sectors of alloc info*/ + *512 /*bytes*/) + -8 /* checksum bytes */) + *8 /* bits per byte */; + //unsigned long clusters=((512*fsc-1)+504)*8; +#if (HD24FSDEBUG_QUICKFORMAT==1) + cout << "Total clusters=" << clusters << endl; +#endif + + unsigned long freeclusters=0; + for (i=0;i99) { + maxprojs=99; + /* safety feature while no larger project + counts are known to be valid; gives + more stability when working with corrupt drives */ + this->writeprotected=true; + } + return maxprojs; +} + +unsigned long hd24fs::getblocksizeinsectors() +{ + if (!(isOpen())) + { + return 0; + } + getsector_bootinfo(); + if (forcemode) { + return 0x480; + } + unsigned long blocksize=Convert::getint32(sector_boot,FSINFO_BLOCKSIZE_IN_SECTORS); + if (blocksize!=0x480) + { + this->writeprotected=true; + } + return blocksize; +} + +unsigned long hd24fs::getbytesperaudioblock() +{ + return getblocksizeinsectors()*512; +} + +unsigned long hd24fs::getblockspercluster() +{ + if (!(isOpen())) + { + return 0; + } + getsector_bootinfo(); + unsigned long maxprojs=Convert::getint32(sector_boot,FSINFO_AUDIOBLOCKS_PER_CLUSTER); + return maxprojs; +} + +unsigned long hd24fs::maxsongsperproject() +{ + if (!(isOpen())) + { + return 0; + } + getsector_bootinfo(); + unsigned long maxsongs=Convert::getint32(sector_boot,FSINFO_MAXSONGSPERPROJECT); + return maxsongs; +} + +__uint32 hd24fs::getprojectsectornum(__uint32 i) +{ +#if (HD24FSDEBUG==1) + cout << "hd24fs::getprojectsectornum("<maxprojects()) + { + return 0; + } + getsector_diskinfo(); + unsigned long projsec=Convert::getint32(sector_diskinfo, + DRIVEINFO_PROJECTLIST+((i-1)*4)); + +#if (HD24FSDEBUG==1) + cout << "projsec = " << projsec << endl; +#endif + return projsec; +} + +void hd24fs::lastprojectid(signed long projectid) +{ + if (!(isOpen())) + { + return; + } + getsector_diskinfo(); + __uint32 lastprojsec=getprojectsectornum(projectid); + if (lastprojsec==0) { + return; + } + if (projectid==lastprojectid()) + { + // nothing changed- nothing to save + return; + } + + Convert::setint32(sector_diskinfo,DRIVEINFO_LASTPROJ,lastprojsec); + savedriveinfo(); + return; +} + +signed long hd24fs::lastprojectid() +{ + if (!(isOpen())) + { + return -1; + } + getsector_diskinfo(); + unsigned long lastprojsec=Convert::getint32(sector_diskinfo,DRIVEINFO_LASTPROJ); + if (lastprojsec==0) { + // TODO: This differs from the real HD24 where even + // on a freshly formatted drive there always is at least + // one project. + return -1; + } + int i; + int maxprojs=maxprojects(); + for (i=1;i<=maxprojs;i++) + { + unsigned long projsec=getprojectsectornum(i); + + if (projsec==lastprojsec) + { + return i; + } + } + // no default project. hm...... + if (maxprojs>=1) { + return 1; + } + return -1; +} + +__uint32 hd24fs::getunusedsongsector() +{ + if (!(isOpen())) + { + return 0; // return 0- this is an invalid songsector + // so error is detectable + } + + // generate an up-to-date song usage table. + unsigned char* songusage=calcsongusage(); + + int currsongentry=0; + signed long foundentry=-1; + int maxprojs=this->maxprojects(); + int maxsongcount=this->maxsongsperproject(); + int totentries=maxprojs*maxsongcount; // 99 songs, 99 projects + while (currsongentrymaxprojects()) return maxprojects(); + + return projcount; +} + +int hd24fs::mode() { + return p_mode; +} + +hd24project* hd24fs::getproject(__sint32 projectid) +{ + __uint32 projsec=getprojectsectornum(projectid); // 1-based + if (projsec==0) { + return NULL; + } + return new hd24project(this,projectid); +} + +hd24project* hd24fs::createproject(const char* projectname) +{ +#if (HD24FSDEBUG==1) + cout << "hd24fs::createproject(" << projectname << ")" << endl; +// cout << "Driveusage before createproject=" << (int)(this->sectors_driveusage) << endl; +#endif + /* This creates a new project (with given project name) + on the drive (if possible). + NULL is returned when unsuccessful, a pointer to the + project otherwise. + */ +#if (HD24FSDEBUG==1) + cout << "hd24fs asked to create project " << projectname << endl; +#endif + int i; + // find first project with project sector num 0! + int maxprojs=maxprojects(); + + getsector_bootinfo(); + if (sector_boot==NULL) { + // unknown cluster size. + return 0; + } + __uint32 firstprojsec=Convert::getint32(sector_boot,FSINFO_FIRST_PROJECT_SECTOR); + cout << "Firstprojsec="<< firstprojsec << endl; + __uint32 secsperproj=Convert::getint32(sector_boot,FSINFO_SECTORS_PER_PROJECT); + cout << "Sectors per project="<< secsperproj << endl; + + // Let's calculate a list of unused project sectors + char* projused=(char*)memutils::mymalloc("createproject",maxprojs,1); + if (projused==NULL) { + return 0; // out of memory + } + + for (i=0;iwriteprotected=true; + return NULL; + } + // Now to assign the first unused project sector + // to the first unused project slot. + + // First, update the drive info. + getsector_diskinfo(); + + // Add the new project pointer to the disk info: + Convert::setint32(sector_diskinfo,DRIVEINFO_PROJECTLIST+(foundslotnum*4),foundsecnum); + Convert::setint32(sector_diskinfo,DRIVEINFO_LASTPROJ,foundsecnum); + + Convert::setint32(sector_diskinfo,DRIVEINFO_PROJECTCOUNT, + Convert::getint32(sector_diskinfo,DRIVEINFO_PROJECTCOUNT)+1); + + bool isnew=true; + hd24project* newproject=new hd24project(this,projectid,foundsecnum,projectname,isnew); + savedriveinfo(); + + return newproject; +} + +bool hd24fs::isallinput() +{ + return this->allinput; +} + +void hd24fs::setallinput(bool p_allinput) +{ + this->allinput=p_allinput; +} + +void hd24fs::setallinput(void) +{ + this->setallinput(true); +} + +/* These three functions are for the 'auto input' button + (having to do with automatic toggling of monitoring + between 'tape' and inputs during a punch in */ +bool hd24fs::isautoinput() +{ + return this->autoinput; +} + +void hd24fs::setautoinput(bool p_autoinput) +{ + this->autoinput=p_autoinput; +} + +void hd24fs::setautoinput(void) +{ + this->setautoinput(true); +} + +void hd24fs::writebackupblock(__uint32 p_sector,__uint32 p_blocksize, + __uint32 lastsec,bool fullcommit) +{ + /** Used by commit. This writes a logical block + of file system data to the end of the drive. */ + unsigned char backbuf[1024]; + + __uint32 i; + __uint32 blocksize=p_blocksize; + + if (fullcommit==false) + { + // we're doing a quick commit, so only backup + // changed blocks. + if (p_sector>highestFSsectorwritten) return; + } + + for (i=1;i<=blocksize;i++) { + // read sector $sector+$i-1 + // write to sector -($sector+1+$blocksize-$i) + // (where -1= last sector) + __uint32 currentsourcesector=p_sector+(i-1); + + readsector_noheader(this, currentsourcesector, backbuf); + __uint32 targetsector=(lastsec-(p_sector+1+blocksize-i))+1; + // cout << "write sec " << targetsector << endl; + writesector(this->devhd24,targetsector,backbuf); + } +} + +bool hd24fs::commit() +{ + // default commit is a quick commit rather than full commit. + // A quick commit only commits sectors up to the last project/song + // sector changed. + return this->commit(false); +} +bool hd24fs::commit(bool fullcommit) +{ + /** This creates a backup of the file system to the end of the drive. */ + + +#if (HD24FSDEBUG==1) + cout << "hd24fs::commit()" << endl; +// cout << "Driveusage before commit=" << (int)(this->sectors_driveusage) << endl; +#endif + if (this->headersectors!=0) + { + // ehm. Obviously we're not going to overwrite the + // end of the drive with header file information, + // as that would defeat the purpose of header files + // (which is to allow safe read-only operation). + return true; + }; + __uint32 sector=0; + __uint32 blocksize=1; + __uint32 count=1; + __uint32 lastsec=getlastsectornum(); + writebackupblock(sector,blocksize,lastsec,fullcommit); // backup superblock + + sector+=(blocksize*count); + blocksize=1; + count=1; + + writebackupblock(sector,blocksize,lastsec,fullcommit); // backup drive info + + sector+=(blocksize*count); + blocksize=3; + count=1; + writebackupblock(sector,blocksize,lastsec,fullcommit); // Backup undo (?) usage + + sector+=(blocksize*count); + blocksize=15; + count=1; + writebackupblock(sector,blocksize,lastsec,fullcommit); // Backup drive usage table + + sector+=(blocksize*count); + blocksize=1; + count=99; + + __uint32 i; + for (i=1;i<=count;i++) + { +#if (HD24FSDEBUG_COMMIT==1) + cout <<"Going to write proj backup block no. " << i << endl; +#endif + writebackupblock(sector+(i-1),blocksize,lastsec,fullcommit); // Backup project + } + + sector+=(blocksize*count); + count=99*99; + for (i=1;i<=count;i++) + { +#if (HD24FSDEBUG_COMMIT==1) + cout <<"Going to write song backup block no. " << i << endl; +#endif + blocksize=2; + writebackupblock(sector+(7*(i-1)),blocksize,lastsec,fullcommit); // Backup song + + blocksize=5; + writebackupblock(sector+(7*(i-1))+2,blocksize,lastsec,fullcommit); // Backup song alloc info + } +#if (HD24FSDEBUG_COMMIT==1) + cout <<"Wrote backup blocks" << endl; + cout << "Driveusage after commit=" << (int)(this->sectors_driveusage) << endl; +#endif + highestFSsectorwritten=0; // reset + return true; +} + +long unsigned int hd24fs::setsectorchecksum(unsigned char* buffer,unsigned int startoffset,unsigned int startsector,unsigned int sectors) +{ + // Calculates and sets the checksum for a block of data. + // Data must be in drive-native format. + long unsigned int checksum32 = 0; + unsigned long int totbytes=(SECTORSIZE*sectors); + + buffer[startoffset+totbytes-8]=startsector%256; + buffer[startoffset+totbytes-7]=(startsector>>8)%256; + buffer[startoffset+totbytes-6]=255- buffer[startoffset+totbytes-8]; + buffer[startoffset+totbytes-5]=255- buffer[startoffset+totbytes-7]; + + for (unsigned long i = 0; i < totbytes; i += 4) + { + unsigned long num = Convert::getint32(buffer, i+startoffset); + int byte1 = num % 256; + int byte2 = (num >> 8) % 256; + int byte3 = (num >> 16) % 256; + int byte4 = (num >> 24) % 256; + num = byte4 + (byte3 << 8) + (byte2 << 16) + (byte1 << 24); + checksum32 += num; + } + unsigned long oldchecksum=0; + oldchecksum+=((unsigned char)(buffer[startoffset+totbytes-1])); oldchecksum=oldchecksum <<8; + oldchecksum+=((unsigned char)(buffer[startoffset+totbytes-2])); oldchecksum=oldchecksum <<8; + oldchecksum+=((unsigned char)(buffer[startoffset+totbytes-3])); oldchecksum=oldchecksum <<8; + oldchecksum+=((unsigned char)(buffer[startoffset+totbytes-4])); + oldchecksum-=checksum32; + buffer[startoffset+totbytes-4]=oldchecksum%256; oldchecksum=oldchecksum >> 8; + buffer[startoffset+totbytes-3]=oldchecksum%256; oldchecksum=oldchecksum >> 8; + buffer[startoffset+totbytes-2]=oldchecksum%256; oldchecksum=oldchecksum >> 8; + buffer[startoffset+totbytes-1]=oldchecksum%256; oldchecksum=oldchecksum >> 8; + return checksum32; +} + +void hd24fs::savedriveinfo() +{ + // This is capable of handling only 1-sector-per-project projects + __uint32 driveinfosector=1; + if (sector_diskinfo==NULL) + { + // diskinfo is not available, nothing to do. + return; + } +#if (HD24FSDEBUG==1) + cout << "FSTFIX" << endl; +#endif + this->fstfix(sector_diskinfo,512); // sector is now once again in native format + +#if (HD24FSDEBUG==1) + cout << "set checksum" << endl; +#endif + this->setsectorchecksum(sector_diskinfo,0,driveinfosector,1); +#if (HD24FSDEBUG==1) + cout << "write sectors" << endl; +#endif + this->writesectors(this->devhd24, + driveinfosector, + sector_diskinfo,1); + +#if (HD24FSDEBUG==1) + cout << "unfix" << endl; +#endif + this->fstfix(sector_diskinfo,512); // sector is now in 'fixed' format +#if (HD24FSDEBUG==1) + cout << "commit" << endl; +#endif + this->commit(); +} + +void hd24fs::setname(unsigned char* namebuf,string newname,__uint32 shortnameoff,__uint32 longnameoff) +{ + /** Used for setting song/project/drive names + Long name is up to 64 characters; short name + is up to 10 chars. + */ +#if (HD24FSDEBUG==1) + cout << "hd24fs::setname(" + << "*namebuf=" << *namebuf << "," + << "newname=" << newname << "," + << "shortnameoff="<fstfix(sectors_driveusage,totsectors*512); // sector is now once again in native format + + this->setsectorchecksum(sectors_driveusage,0,driveusagesector,totsectors); + this->writesectors(this->devhd24, + driveusagesector, + sectors_driveusage,totsectors); + + this->fstfix(sectors_driveusage,totsectors*512); // sector is now in 'fixed' format +#if (HD24FSDEBUG==1) + cout << "free cluster count=" << freeclustercount() << endl; +#endif + unsigned char* bootrec=readbootinfo(); + // update FSINFO_FREE_CLUSTERS_ON_DISK + + Convert::setint32(bootrec,FSINFO_FREE_CLUSTERS_ON_DISK,freeclustercount()); + fstfix(bootrec,512); // convert back into native format + + /* Calculate the proper checksum for the bootinfo */ + setsectorchecksum(bootrec, + 0 /* startoffset */, + 0 /* sector */, + 1 /*sectorcount */ + ); + this->writesectors(this->devhd24, 0,bootrec,1); + fstfix(bootrec,512); // convert back into fixed format + this->commit(); +} + + +__uint32 hd24fs::writesuperblock(__uint32 lastsec) +{ + // writes a new superblock to an unformatted drive. + // + // normal start of data area=1397f6 + // size of 1 audio block=0x480 sectors + // fs size=0x77+7*99 + // so minimum usable drive is 0x1397f6+0x480+(0x77+(7*99*99)) + // =0x14a8ec sectors + if (lastsec<0x14a8ec) + { + // drive is smaller than the minimum needed for + // storing at least 1 audio block. + return RESULT_FAIL; + } + unsigned char superblock[512]; + useinternalboot(superblock,lastsec); // this automatically sets sector checksum + writesectors(this->devhd24,0,&superblock[0],1); +#if (HD24FSDEBUG_QUICKFORMAT==1) + + cout << "Writing superblock." << endl; + dumpsector((const char*)superblock); + +#endif + + force_reload(); + + readbootinfo(); + +#if (HD24FSDEBUG_CLUSTERddCALC==1) + cout << "Displaying sector after reload." << endl; + dumpsector((const char*)sector_boot); +#endif + + return RESULT_SUCCESS; +} + +void hd24fs::force_reload() +{ +#if (HD24FSDEBUG==1) + cout << "Free superblock mem" << endl; +#endif + if (sector_boot!=NULL) + { + memutils::myfree("sectors_boot",sector_boot); + sector_boot=NULL; + } +#if (HD24FSDEBUG==1) + cout << "Free diskinfo mem" << endl; +#endif + if (sector_diskinfo!=NULL) + { + memutils::myfree("sectors_diskinfo",sector_diskinfo); + sector_diskinfo=NULL; + } +#if (HD24FSDEBUG==1) + cout << "Free drive usage mem" << endl; +#endif + if (sectors_driveusage!=NULL) + { + memutils::myfree("sectors_driveusage",sectors_driveusage); + sectors_driveusage=NULL; + } +#if (HD24FSDEBUG==1) + cout << "Free orphan sectors mem" << endl; +#endif + if (sectors_orphan!=NULL) + { + memutils::myfree("sectors_orphan",sectors_orphan); + sectors_orphan=NULL; + } +#if (HD24FSDEBUG==1) + cout << "Free song usage sectors mem" << endl; +#endif + if (sectors_songusage!=NULL) + { + memutils::myfree("sectors_songusage",sectors_songusage); + sectors_songusage=NULL; + }; + +} +__uint32 hd24fs::writedriveinfo() +{ + readdiskinfo(); + cleardriveinfo(sector_diskinfo); + fstfix(sector_diskinfo,512); // back into native format + writesectors(this->devhd24,1,sector_diskinfo,1); + if (sector_diskinfo!=NULL) { + memutils::myfree("sector_diskinfo",sector_diskinfo); + sector_diskinfo=NULL; // force re-read + } + hd24project* firstproject=createproject("Proj Name"); + memutils::myfree("firstproject",firstproject); + + if (sector_diskinfo!=NULL) { + memutils::myfree("sector_diskinfo",sector_diskinfo); + sector_diskinfo=NULL; // force re-read + } + __uint32 psec=getprojectsectornum(1); + if (sector_diskinfo!=NULL) { + memutils::myfree("sector_diskinfo",sector_diskinfo); + sector_diskinfo=NULL; // force re-read + } + readdiskinfo(); + Convert::setint32(sector_diskinfo,DRIVEINFO_LASTPROJ,psec); + savedriveinfo(); + + return RESULT_SUCCESS; +} + +__uint32 hd24fs::writesongusage() +{ + unsigned char* buffer=resetsongusage(); + if (buffer==NULL) + { + return RESULT_FAIL; + } + __uint32 sectornum=2; + __uint32 sectorcount=3; + fstfix(buffer,sectorcount*512); + setsectorchecksum(buffer, + 0 /* startoffset */, + sectornum /* sector */, + sectorcount /*sectorcount */ + ); + this->writesectors(this->devhd24, + sectornum, + buffer, + sectorcount); + fstfix(buffer,sectorcount*512); + return RESULT_SUCCESS; +} + +__uint32 hd24fs::writedriveusage() +{ + if (sectors_driveusage!=NULL) + { + memutils::myfree("sectors_driveusage",sectors_driveusage); + sectors_driveusage=NULL; + } + + unsigned char* buffer=resetdriveusage(); + if (buffer==NULL) + { + return RESULT_FAIL; + } + __uint32 sectornum=5; + __uint32 sectorcount=15; + fstfix(buffer,sectorcount*512); + setsectorchecksum(buffer, + 0 /* startoffset */, + sectornum /* sector */, + sectorcount /*sectorcount */ + ); + + this->writesectors(this->devhd24, + sectornum, + buffer, + sectorcount); + fstfix(buffer,sectorcount*512); + + return RESULT_SUCCESS; +} + +__uint32 hd24fs::quickformat(char* message) +{ + // This procedure performs a quickformat on the current drive. + // There is no need for the drive to be a valid HD24 drive + // for this to work. + // Safety confirmations etc. are considered to be the + // responsibility of the caller. + + gotlastsectornum=false; // force re-finding last sector num + __uint32 lastsec=getlastsectornum(); + + formatting=true; + + if (lastsec==0) + { + if (message!=NULL) strcpy(message,(const char*)&"Lastsec=0"); + return 0; + } + __uint32 result=writesuperblock(lastsec); + + if (result==RESULT_FAIL) + { + if (message!=NULL) strcpy(message,(const char*)&"Write superblock failed"); + return 0; // lastsec 0 means failed format + } + + result=writedriveinfo(); + if (result==RESULT_FAIL) + { + if (message!=NULL) strcpy(message,(const char*)&"Write driveinfo failed"); + return 0; // lastsec 0 means failed format + } + + result=writesongusage(); + if (result==RESULT_FAIL) + { + if (message!=NULL) strcpy(message,(const char*)&"Write song usage failed"); + return 0; // lastsec 0 means failed format + } + + result=writedriveusage(); + if (result==RESULT_FAIL) + { + if (message!=NULL) strcpy(message,(const char*)&"Write drive usage failed"); + return 0; // lastsec 0 means failed format + } + + // write empty song-entry usage table + // write empty drive usage table + // write 99 empty projects + // create default project + // (write 99*99 empty songs) + // (empty audio space) + // commit fs + commit(); + formatting=false; + force_reload(); + return lastsec; +} + +void hd24fs::setprojectsectornum(int i,__uint32 sector) +{ + getsector_diskinfo(); + Convert::setint32(sector_diskinfo, + DRIVEINFO_PROJECTLIST + ((i - 1) * 4),sector); + + return; +} + +__uint32 hd24fs::deleteproject(__sint32 projid) +{ + if (projid<1) + { + /* Illegal project id; + project IDs are set in base 1. */ + return RESULT_FAIL; + } + + getsector_diskinfo(); // has list of pointers to project sectors + __uint32 pcount = Convert::getint32(sector_diskinfo, DRIVEINFO_PROJECTCOUNT); + + if (pcount<=1) + { + /* Attempt to delete last project on drive- + not allowed, a drive must always contain + at least 1 project */ + return RESULT_FAIL; + } + + hd24project* projtodel=this->getproject(projid); + if (projtodel==NULL) { + return RESULT_FAIL; + } + + /* If there still all songs in the project, delete them */ + __uint32 currsongcount=projtodel->songcount(); + if (currsongcount>0) + { + for (__uint32 j=1; j<=currsongcount;j++) + { + projtodel->deletesong(1); // songs will shift + projtodel->save(); + } + } + + /* delete project from project list by shifting left + all other projects... */ + if (projid<99) + { + /* When project 99 is deleted no shifting is needed */ + for (__uint32 i=projid;i<99;i++) + { + setprojectsectornum(i,getprojectsectornum(i+1)); + } + } + + setprojectsectornum(99,0); // ...and clearing the last entry. + + Convert::setint32(sector_diskinfo,DRIVEINFO_PROJECTCOUNT,pcount-1); + + /* Set 'last accessed project' to first in list + (the project being deleted needs to be accessed + prior to deletion so this must always be updated) + */ + Convert::setint32(sector_diskinfo, DRIVEINFO_LASTPROJECT,getprojectsectornum(1)); +#if (HD24FSDEBUG==1) + cout << "save project." << endl; +#endif + + savedriveinfo(); + delete projtodel; + return RESULT_SUCCESS; +} + +void hd24fs::write_enable() +{ + this->writeprotected=false; +} + +void hd24fs::write_disable() +{ + this->writeprotected=true; +} + 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 @@ +#ifndef __hd24fs_h__ +#define __hd24fs_h__ + +#include +#include +#include +#include +#include "memutils.h" +#include "convertlib.h" +#define CLUSTER_UNDEFINED (0xFFFFFFFF) + +#if defined(LINUX) || defined(DARWIN) +# define FSHANDLE int +# define FSHANDLE_INVALID -1 +#endif + +#ifdef WINDOWS +# include +# include +# define FSHANDLE HANDLE +# define FSHANDLE_INVALID INVALID_HANDLE_VALUE +#endif + +using namespace std; + +class hd24fs; +class hd24project; +class hd24raw; +class hd24song; + +class AudioStorage +{ +public: + virtual __uint32 samplerate() { return 0; }; + virtual void currentlocation(__uint32 newpos) { return; }; + virtual __uint32 currentlocation() { return 0; }; + virtual __uint32 getlocatepos(int locatepoint) { return 0; }; + virtual __uint32 setlocatepos(int locatepoint,__uint32 newpos) { return 0; }; + virtual bool trackarmed(__uint32 base1tracknum) { return false; } + virtual void trackarmed(__uint32 base1tracknum,bool arm) { return; } + virtual ~AudioStorage() { return; } ; +}; + +class hd24song : public AudioStorage +{ + friend class hd24project; + friend class hd24fs; + friend class hd24transferjob; + friend class hd24transferengine; + private: + __uint32 framespersec; + unsigned char* buffer; // for songinfo + unsigned char* audiobuffer; // for audio data + unsigned char* scratchbook; // for write-back audio data + __uint32* blocksector; + int evenodd; /* specifies if we are dealing with + even or odd samples in high speed mode. */ + bool lengthened; /* Indicate if reallocating song length change occured */ + bool busyrecording; + int mysongid; + int polling; + int currentreadmode; + int currcachebufnum; + bool rehearsemode; + bool lastallocentrynum; + hd24fs* parentfs; + unsigned char** cachebuf_ptr; + __uint32* cachebuf_blocknum; + hd24project* parentproject; + hd24song(hd24project* p_parent,__uint32 p_songid); + unsigned char* getcachedbuffer(long unsigned int); + void queuecacheblock(__uint32 blocknum); + void loadblockintocache(__uint32 blocknum); + void setblockcursor(__uint32 blocknum); + void memoizeblocksectors(__uint32 lastblock); + __uint32 memblocksector(__uint32 blocknum); + __uint32 blocktoqueue; // next block to cache + __uint32 songcursor; // current cursor pos within song, in samples + __uint32 allocentrynum; // which allocation entry is currently being used + __uint32 allocstartblock; // the first audioblock in given entry + __uint32 allocstartsector; // the sector pointed to by that entry + __uint32 allocaudioblocks; // the number of audioblocks in the block + __uint32 divider; + __uint32 lastreadblock; + __uint32 lastavailablecacheblock; + __uint32 mustreadblock; + __uint32 track_armed[24]; + __uint32 track_readenabled[24]; // used to speed up copy mode. + void unmark_used_clusters(unsigned char* sectors_orphan); + __uint32 used_alloctable_entries(); + __uint32 audioblocks_in_alloctable(); + void silenceaudioblocks(__uint32 allocsector,__uint32 blocks); + bool allocatenewblocks(long unsigned int, bool, char*, int*, int (*)()); + + public: + ~hd24song(); + string* songname(); + __uint32 songid(); + hd24fs* fs(); + static void sectorinit(unsigned char* sectorbuf); + static void settrackcount(unsigned char* sectorbuf,__uint32 trackcount); + static void songname(unsigned char* sectorbuf,string newname); + void songname(string newname); + static string* songname(hd24fs* parentfs,unsigned char* sectorbuf); + void bufferpoll(); + + void readenabletrack(__uint32 tracknum); + void readenabletrack(__uint32 tracknum,bool enable); + + bool isrehearsemode(); + void setrehearsemode(bool p_rehearsemode); + bool recording(); + + bool trackarmed(__uint32 tracknum); + void trackarmed(__uint32 tracknum,bool arm); + + bool istrackmonitoringinput(__uint32 tracknum); + void startrecord(int record_mode); + void stoprecord(); + __uint32 samplerate(); + static void samplerate(unsigned char* sectorbuf,__uint32 samplerate); + void samplerate(__uint32 newrate); + static __uint32 samplerate(unsigned char* songbuf); + __uint32 bitdepth(); + __uint32 physical_channels(); + static __uint32 physical_channels(unsigned char* songbuf); + void physical_channels(__uint32 newchannelcount); + static void physical_channels(unsigned char* songbuf,__uint32 newchannelcount); + __uint32 logical_channels(); + static __uint32 logical_channels(unsigned char* songbuf); + void logical_channels(__uint32 newchannelcount); + static void logical_channels(unsigned char* songbuf,__uint32 channelcount); + __uint32 songlength_in_samples(); + __uint32 songlength_in_samples(__uint32 newlen); + __uint32 songlength_in_samples(__uint32 newlen,bool silence); + __uint32 songlength_in_samples(__uint32 newlen,bool silence,char* savemessage,int* cancel); + __uint32 songlength_in_samples(__uint32 newlen,bool silence,char* savemessage,int* cancel,int (*checkfunc)()); + + __uint32 display_hours(); + __uint32 display_hours(__uint32 offset); + static __uint32 display_hours(__uint32 offset,__uint32 samrate); + + __uint32 display_minutes(); + __uint32 display_minutes(__uint32 offset); + static __uint32 display_minutes(__uint32 offset,__uint32 samrate); + + __uint32 display_seconds(); + __uint32 display_seconds(__uint32 offset); + static __uint32 display_seconds(__uint32 offset,__uint32 samrate); + + __uint32 display_subseconds(); + __uint32 display_subseconds(__uint32 offset); + static __uint32 display_subseconds(__uint32 offset,__uint32 samrate); + + string* display_duration(); + string* display_duration(__uint32 offset); + string* display_duration(__uint32 offset,__uint32 samrate); + + string* display_cursor(); + __uint32 cursorpos(); + __uint32 locatepointcount(); + __uint32 getlocatepos(int locatepoint); + + __uint32 currentlocation(); + void currentlocation(__uint32 offset); + __uint32 golocatepos(__uint32 offset); + + __uint32 setlocatepos(int locatepoint,__uint32 offset); + void setlocatename(int locatepoint,string newname); + string* getlocatename(int locatepoint); + bool iswriteprotected(); + void setwriteprotected(bool prot); + void getmultitracksample(long* mtsample,int readmode); + int getmtrackaudiodata(__uint32 firstsamnum,__uint32 samples,unsigned char* buffer,int readmode); + int putmtrackaudiodata(__uint32 firstsamnum,__uint32 samples,unsigned char* buffer,int writemode); + void deinterlaceblock(unsigned char* buffer,unsigned char* targetbuffer); + void interlaceblock(unsigned char* buffer,unsigned char* targetbuffer); + static const int LOCATEPOS_SONGSTART; + static const int LOCATEPOS_LOOPSTART; + static const int LOCATEPOS_LOOPEND; + static const int LOCATEPOS_PUNCHIN; + static const int LOCATEPOS_PUNCHOUT; + static const int LOCATEPOS_EDITIN; + static const int LOCATEPOS_EDITOUT; + static const int LOCATEPOS_LAST; + static const int READMODE_COPY; + static const int READMODE_REALTIME; + static const int WRITEMODE_COPY; + static const int WRITEMODE_REALTIME; + + __uint32 getnextfreesector(__uint32 allocsector); + bool has_unexpected_end(); // indicates if there is an 'unexpected end of song' error + bool is_fixable_unexpected_end(); // ...and if so, if we know how to fix it. + bool setallocinfo(bool silencenew); + bool setallocinfo(bool silencenew,char* message,int* cancel,int (*checkfunc)()); + __uint32 requiredaudioblocks(__uint32 songlen); + void appendorphanclusters(unsigned char*,bool allowsongresize); + void save(); +}; + +class hd24project +{ + friend class hd24fs; + friend class hd24song; + + private: + unsigned char* buffer; + hd24fs* parentfs; + __sint32 myprojectid; + hd24song* songlist; + hd24project(hd24fs* p_parent,__sint32 projectid); + hd24project(hd24fs* p_parent,__sint32 projectid,__uint32 projsector,const char* projectname,bool isnew); + __uint32 getsongsectornum(int i); + void setsongsectornum(int i,__uint32 newsector); + void save(__uint32 projsector); + void populatesongusagetable(unsigned char* songused); + __uint32 getunusedsongslot(); + void initvars(hd24fs* p_parent,__sint32 p_projectid); + public: + ~hd24project(); + string* projectname(); + void projectname(string newname); + __sint32 lastsongid(); + void lastsongid(signed long songid); + __uint32 songcount(); + __uint32 maxsongs(); + __sint32 projectid(); + hd24song* getsong(__uint32 songid); + hd24song* createsong(const char* songname,__uint32 trackcount,__uint32 samplerate); + __uint32 deletesong(__uint32 songid); + void save(); + void sort(); +}; + +class hd24fs +{ + friend class hd24project; + friend class hd24song; + friend class hd24raw; + friend class hd24utils; + + private: + const char* imagedir; + int transportstatus; + bool writeprotected; + bool allinput; + bool autoinput; + bool forcemode; + bool formatting; // true during a format operation + bool headermode; + bool maintenancemode; + bool wavefixmode; + __uint32 highestFSsectorwritten; + + __uint32 nextfreeclusterword; // memoization cache for write allocation + + FSHANDLE devhd24; // device handle + FSHANDLE hd24header; // header device handle + bool m_isOpen; + bool gotlastsectornum; + __uint32 foundlastsectornum; + int p_mode; + hd24project* projlist; + string* devicename; + unsigned char* sector_boot; + unsigned char* sector_diskinfo; + unsigned char* sectors_driveusage; + unsigned char* sectors_orphan; + unsigned char* sectors_songusage; + long readsectors(FSHANDLE handle, __uint32 secnum, unsigned char* buffer,int sectors); + long readsector(FSHANDLE handle, __uint32 secnum, unsigned char* buffer); + long readsector_noheader(FSHANDLE handle, __uint32 secnum, unsigned char* buffer); + long readsector_noheader(hd24fs* currenthd24, __uint32 secnum, unsigned char* buffer); + long writesectors(FSHANDLE handle, __uint32 secnum, unsigned char* buffer,int sectors); + long writesector(FSHANDLE handle, __uint32 secnum, unsigned char* buffer); + + string* gethd24currentdir(int, char**); + void hd24close(); + void hd24closedevice(FSHANDLE handle); + static void hd24seek(FSHANDLE handle,__uint64 seekpos); + void clearbuffer(unsigned char* buffer); + void clearbuffer(unsigned char* buffer,unsigned int bytes); + FSHANDLE findhd24device(); + FSHANDLE findhd24device(int mode); + FSHANDLE findhd24device(int mode, int base0devnum); + FSHANDLE findhd24device(int mode, string* dev,bool force,bool tryharder); + static bool isinvalidhandle(FSHANDLE handle); + unsigned char* readbootinfo(); + unsigned char* readdiskinfo(); + unsigned char* readdriveusageinfo(); + unsigned char* resetsongusage(); + unsigned char* resetdriveusage(); + unsigned char* calcsongusage(); + void refreshsongusage(); + unsigned char* getsector_bootinfo(); + unsigned char* getsector_diskinfo(); + unsigned char* getsectors_driveusage(); + unsigned char* getcopyofusagetable(); // allocates memory and fills it up with a copy of the current usage table + void initvars(); + __uint32 driveusagesectorcount(); + __uint32 clustercount(); + __uint32 driveusagefirstsector(); + __uint32 getblockspercluster(); + __uint32 getprojectsectornum(__uint32 base1proj); + bool isfreecluster(__uint32 clusternum); + bool isfreecluster(__uint32 clusternum,unsigned char* usagebuffer); + __uint32 freeclustercount(); + __uint32 getlastsectornum(); + __uint32 getlastsectornum(FSHANDLE handle); + __uint32 headersectors; + void writebackupblock(__uint32 sector,__uint32 blocksize, + __uint32 lastsec,bool fullcommit); + __uint32 getnextfreesectorword(); + __uint32 getnextfreeclusterword(); + __uint32 getnextfreesector(__uint32 cluster); + void enablebit(__uint32 ibit,unsigned char* usagebuffer); + void disablebit(__uint32 ibit,unsigned char* usagebuffer); + bool isbitzero(__uint32 ibit,unsigned char* usagebuffer); + long unsigned int songentry2songsector(long unsigned int entry); + long unsigned int songsector2songentry(long unsigned int entry); + void allocsongentry(__uint32 entrynum); + void allocatecluster(__uint32 clusternum); + void allocatecluster(__uint32 clusternum,unsigned char* usagebuffer); + void freecluster(__uint32 clusternum); + void freecluster(__uint32 clusternum,unsigned char* usagebuffer); + signed long nextunusedsongentry(); + void useinternalboot(unsigned char*, long unsigned int); + __uint32 getunusedsongsector(); + __uint32 songsondisk(); + void songsondisk(__uint32 songsondisk); + void setprojectsectornum(int i,__uint32 newsector); + void setimagedir(const char* newdir); + int deviceid; + public: + __uint32 lasterror; + void force_reload(); + static void setname(unsigned char* namebuf,string newname,__uint32 shortnameoff,__uint32 longnameoff); + void dumpclusterusage(); + void dumpclusterusage(unsigned char* buffer); + void dumpclusterusage2(); + void dumpclusterusage2(unsigned char* buffer); + unsigned char* findorphanclusters(); + static const int TRANSPORTSTATUS_PLAY; + static const int TRANSPORTSTATUS_STOP; + static const int TRANSPORTSTATUS_REC; + __uint32 cluster2sector(__uint32 clusternum); + __uint32 sector2cluster(__uint32 sectornum); + __uint32 songentry2sector(__uint32 entrynum); + __uint32 songsector2entry(__uint32 sectornum); + void settransportstatus(int newstatus); + int gettransportstatus(); + bool isallinput(); + void setallinput(bool p_allinput); + void setallinput(void); + bool isautoinput(); + void setautoinput(bool p_autoinput); + void setautoinput(void); + + hd24fs(const char* imagedir); + hd24fs(const char* imagedir,int mode); + hd24fs(const char* imagedir,int mode,int base0devnum); + hd24fs(const char* imagedir,int mode,string* dev,bool force); + ~hd24fs(); + __uint32 getblocksizeinsectors(); + __uint32 getbytesperaudioblock(); + static void fstfix(unsigned char* bootblock,int fixsize); + bool isOpen(); + int mode(); + string* volumename(); + string* getdevicename(); + int getdeviceid(); + void setdevicename(const char* orig,string* newname); + void setvolumename(string newname); + string* version(); + __uint32 hd24devicecount(); + __sint32 lastprojectid(); + void lastprojectid(signed long projectid); + __uint32 projectcount(); + __uint32 maxprojects(); + __uint32 maxsongsperproject(); + hd24project* getproject(__sint32 projectid); + hd24project* createproject(const char* projectname); + void setmaintenancemode(int mode); + int getmaintenancemode(); + void setwavefixmode(int mode); + int getwavefixmode(); + string* gethd24currentdir(); + static const int MODE_RDONLY; + static const int MODE_RDWR; + string* freespace(__uint32 rate,__uint32 tracks); + bool useheaderfile(string headerfilename); + bool isexistingdevice(string *devname); + bool commit(bool fullcommit); + bool commit(); + long unsigned int setsectorchecksum(unsigned char* buffer,unsigned int startoffset,unsigned int startsector,unsigned int sectors); + void savedriveinfo(); + void savedriveusage(); + __uint32 writesuperblock(__uint32 lastsectornum); + void cleardriveinfo(unsigned char* buffer); + __uint32 writedriveinfo(); + __uint32 writesongusage(); + __uint32 writedriveusage(); + __uint32 quickformat(char* lasterror); + __uint32 deleteproject(__sint32 projid); + void write_enable(); + void write_disable(); +}; + +/* Provides sector level access to hd24 disks + * (functionality which is private in hd24fs) + */ +class hd24raw +{ + friend class hd24fs; + + private: + hd24fs* fsys; + + public: + hd24raw(hd24fs* fsys); + hd24raw(hd24fs* fsys,bool notranslate); + ~hd24raw() {}; + long readsectors(__uint32 secnum, unsigned char* buffer,int sectors); + long writesectors(__uint32 secnum, unsigned char* buffer,int sectors); + __uint32 getnextfreesector(__uint32 cluster); + __uint32 getprojectsectornum(__uint32 projectid); + __uint32 getlastsectornum(); + __uint32 songsondisk(); + __uint32 quickformat(char* lasterror); +}; + +#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 @@ +#define PROJDEBUG 0 +#define PROJINFO_PROJECTNAME_8 0x0 +#define PROJINFO_SONGCOUNT 0x0c +#define PROJINFO_LASTSONG 0x10 +#define PROJINFO_SONGLIST 0x20 +#define PROJINFO_PROJECTNAME 0x1b8 +#define INVALID_SONGENTRY 0xFFFFFFFF +#define RESULT_SUCCESS 0 +#define RESULT_FAIL 1 +#include +#include "memutils.h" +void hd24project::initvars(hd24fs* p_parent,__sint32 p_myprojectid) +{ + this->myprojectid=p_myprojectid; + this->parentfs = p_parent; + return; +} + +__sint32 hd24project::projectid() +{ + return this->myprojectid; +} + +hd24project::hd24project(hd24fs* p_parent, __sint32 p_myprojectid, + __uint32 p_projectsector, const char* p_projectname, + bool isnew) +{ +#if (PROJDEBUG == 1) + cout << "CONSTRUCT hd24project " << p_myprojectid << endl; +#endif + // initialize a new project. + // Boolean is obligatory to prevent accidents; + // one can still create a project and not save it immediately. + this->myprojectid = p_myprojectid; + buffer = (unsigned char*)memutils::mymalloc("hd24project(1)",1024,1); + parentfs = p_parent; + if (!isnew) { + p_parent->readsector(p_parent->devhd24, + p_parent->getprojectsectornum(myprojectid), + buffer); // fstfix follows + + p_parent->fstfix(buffer, 512); + projectname(p_projectname); + } else { +#if (PROJDEBUG == 1) + cout << "Create new project " <save(p_projectsector); + } +} + +hd24project::hd24project(hd24fs* p_parent, __sint32 p_myprojectid) +{ + // project id is 1-based +#if (PROJDEBUG == 1) + cout << "Here we are. time to create the project object for proj. " + << p_myprojectid << endl; +#endif + this->myprojectid = p_myprojectid; + buffer = (unsigned char*)memutils::mymalloc("hd24project(2)",1024,1); + if (buffer==NULL) { + return; + } + parentfs = p_parent; + __uint32 projsecnum=p_parent->getprojectsectornum(myprojectid); + if (projsecnum==0) { + for (int i=0;i<512;i++) { + buffer[i]=0; + } + } else { + p_parent->readsector(p_parent->devhd24, + projsecnum, + buffer); // fstfix follows + + p_parent->fstfix(buffer, 512); + //this->sort(); + } + +} + +hd24project::~hd24project() +{ +#if (PROJDEBUG == 1) + cout << "DESTRUCT hd24project " << myprojectid << endl; +#endif + if (buffer != NULL) memutils::myfree("hd24project::buffer",buffer); +} + +string* hd24project::projectname() +{ + string* ver=parentfs->version(); + if (*ver == "1.00") + { + delete ver; + // version 1.0 filesystem. + string* tmp = new string(""); + string* dummy = Convert::readstring(buffer, PROJINFO_PROJECTNAME_8, 8); + + *tmp += *dummy; + delete dummy; + + if (tmp->length() == 8) + { + dummy = Convert::readstring(buffer, PROJINFO_PROJECTNAME_8 + 10, 2); + *tmp += *dummy; + delete dummy; + } + + return tmp; + } + delete ver; + return Convert::readstring(buffer, PROJINFO_PROJECTNAME, 64); +} + +void hd24project::projectname(string newname) +{ + hd24fs::setname(this->buffer,newname,PROJINFO_PROJECTNAME_8,PROJINFO_PROJECTNAME); + return; +} + +unsigned long hd24project::maxsongs() +{ + return parentfs->maxsongsperproject(); +} + +unsigned long hd24project::getsongsectornum(int i) +{ + unsigned int songsec = Convert::getint32(buffer, + PROJINFO_SONGLIST + ((i - 1) * 4)); + // FIXME: Check for sensible values. + return songsec; +} + +void hd24project::setsongsectornum(int i,__uint32 sector) +{ + Convert::setint32(buffer, + PROJINFO_SONGLIST + ((i - 1) * 4),sector); + // FIXME: Check for sensible values. + return; +} + +void hd24project::lastsongid(signed long songid) +{ + if (songid<1) + { + return; + + } + int maxsongsperproj = maxsongs(); + if (songid>maxsongsperproj) + { + return; + } + if (songid==lastsongid()) + { + /* same 'last song id' as before- + nothing changes. + */ + return; + } + Convert::setint32(buffer, PROJINFO_LASTSONG,getsongsectornum(songid)); + this->save(); + return; +} + +signed long hd24project::lastsongid() +{ + unsigned int lastsongsec = Convert::getint32(buffer, PROJINFO_LASTSONG); + + if (lastsongsec == 0) + { + return -1; + } + + int maxsongsperproj = maxsongs(); + for (int i = 1; i <= maxsongsperproj; i++) + { + unsigned int songsec = getsongsectornum(i); + + if (songsec == lastsongsec) + { + return i; + } + } + + if (maxsongsperproj >= 1) + { + return 1; + } + + return -1; +} + +__uint32 hd24project::songcount() +{ + if (this==NULL) + { + return 0; + } + if (myprojectid == -1) + { + return 0; + } + if (buffer==NULL) { + return 0; + } + __uint32 scount = Convert::getint32(buffer, PROJINFO_SONGCOUNT); + + if (scount > 99) + { + return 99; + } + + return scount; +} + +hd24song* hd24project::getsong(unsigned long songid) +{ +#if (PROJDEBUG == 1) + cout << "get song " << songid << endl; +#endif + return new hd24song(this,songid); +} + +void hd24project::save(__uint32 projsector) +{ +#if (PROJDEBUG == 1) + cout << "save project info to sector " << projsector << endl; +#endif + if (buffer==NULL) + { + return; // nothing to do! + } + parentfs->fstfix(buffer,512); // sector is now in native format again + parentfs->setsectorchecksum(buffer,0,projsector,1); + parentfs->writesectors(parentfs->devhd24, + projsector, + buffer,1); + + parentfs->fstfix(buffer,512); // sector is now in 'fixed' format + parentfs->commit(); +} + +void hd24project::save() +{ + // This is capable of handling only 1-sector-per-project projects. + // save(projsector) is only intended for new projects. + __uint32 projsector=parentfs->getprojectsectornum(this->myprojectid); +#if (PROJDEBUG == 1) + cout << "save project info to sector " << projsector << endl; +#endif + if (projsector==0) + { + return; // safety measure + } + save(projsector); +} + +__uint32 hd24project::getunusedsongslot() +{ + // Find the first unused song slot in the current project. + __uint32 unusedsongslot=INVALID_SONGENTRY; + + int maxsongcount=this->maxsongs(); + for (int j=1; j<=maxsongcount;j++) + { + // get song sector info. + __uint32 songsector = getsongsectornum(j); + if (songsector==0) + { + unusedsongslot=(j-1); + break; + } + } + + return unusedsongslot; +} + +hd24song* hd24project::createsong(const char* songname,__uint32 trackcount, + __uint32 samplerate) +{ + /* This creates a new song (with given songname) + on the drive (if possible). + NULL is returned when unsuccessful, a pointer to the + new song object otherwise. + */ + __uint32 songslot=getunusedsongslot(); + if (songslot==INVALID_SONGENTRY) + { + // project is full. + return NULL; + } + + // Project is not full so there must be unused song sectors + // (if not, something seriously fishy is going on). + __uint32 newsongsector=this->parentfs->getunusedsongsector(); + if (newsongsector==0) + { + // no songsector found (0 is not a valid songsector) + return NULL; + } + + // So, we have got a free songsector and a free song slot. + unsigned char songbuf[512*7]; + for (int i=0;i<(7*512);i++) + { + songbuf[i]=(unsigned char)(0); + } + hd24song::sectorinit(songbuf); // put some default info in there + + hd24song::songname((unsigned char*)songbuf,songname); + string* setsongname=hd24song::songname(parentfs,songbuf); + delete setsongname; + + hd24song::samplerate((unsigned char*)songbuf,samplerate); + hd24song::logical_channels((unsigned char*)songbuf,trackcount) ;// depends on samplerate + __uint32 songsector=newsongsector; + + // - Create the empty song at the songsector + // (2 sectors in size) + // - Create empty allocation info at songsector+2 + // (5 sectors in size) + // write song info to drive + + parentfs->fstfix(songbuf,TOTAL_SECTORS_PER_SONG*512); // sector is now once again in native format + parentfs->setsectorchecksum(songbuf,0,songsector,2); + parentfs->setsectorchecksum(songbuf,2*512,songsector+2,5); + parentfs->writesectors(parentfs->devhd24,songsector,songbuf,TOTAL_SECTORS_PER_SONG); + parentfs->fstfix(songbuf,TOTAL_SECTORS_PER_SONG*512); // sector is now once again in fixed format + + ///////////////////////////// + // -Update the project slot info to point at that sector + Convert::setint32(buffer,PROJINFO_SONGLIST+(songslot*4),songsector); + this->lastsongid(songslot+1); + Convert::setint32(buffer,PROJINFO_SONGCOUNT, + Convert::getint32(buffer,PROJINFO_SONGCOUNT)+1); + this->save(); + parentfs->refreshsongusage(); + + //////////////////////// + // Now commit the FS + parentfs->commit(); + + return getsong(songslot+1); +} + +__uint32 hd24project::deletesong(__uint32 songid) +{ + hd24song* songtodel=this->getsong(songid); +#if (PROJDEBUG == 1) + cout << "del song with id " << songid << endl; +#endif + __uint32 songsector=getsongsectornum(songid); +#if (PROJDEBUG == 1) + cout << "sector " << songsector << endl; +#endif + songsector++; songsector--; // prevent 'variable not used' warning + + if (songtodel==NULL) + { +#if (PROJDEBUG == 1) + cout << "song to del==null " << endl; +#endif + return RESULT_FAIL; + } + songtodel->songlength_in_samples(0,false); + songtodel->save(); + + // delete song from project list by shifting left + // all other songs... + for (__uint32 i=songid;i<99;i++) + { +#if (PROJDEBUG == 1) + cout << "set new sector for song id " << i <<" to " << getsongsectornum(i+1) << endl; +#endif + setsongsectornum(i,getsongsectornum(i+1)); + } + setsongsectornum(99,0); // ...and clearing the last entry. + __uint32 scount = Convert::getint32(buffer, PROJINFO_SONGCOUNT); + Convert::setint32(buffer,PROJINFO_SONGCOUNT,scount-1); +#if (PROJDEBUG == 1) + cout << "set new song count to " << (scount-1) << endl; +#endif + + // set 'last accessed song' to first song in list + // (if there are no songs anymore, this automatically + // results in 'last song' to be on sector zero. +#if (PROJDEBUG ==1) + cout << "set default project song to song 1 with sectornum " << getsongsectornum(1) << endl; +#endif + Convert::setint32(buffer, PROJINFO_LASTSONG,getsongsectornum(1)); +#if (PROJDEBUG ==1) + cout << "save project." << endl; +#endif + + this->save(); +#if (PROJDEBUG ==1) + cout << "refresh song usage table (+superblock) " << endl; +#endif + parentfs->refreshsongusage(); // or calcsongusage? + + unsigned char* sectors_driveusage=parentfs->getsectors_driveusage(); + + // now, we still have the song object songtodel, + // plus its original sector number. +#if (PROJDEBUG ==1) + cout << "Reset song length" << endl; +#endif +#if (PROJDEBUG ==1) + cout << "Unmark used clusters " << endl; +#endif + songtodel->unmark_used_clusters(sectors_driveusage); +#if (PROJDEBUG ==1) + cout << "Destruct song object." << endl; +#endif + delete(songtodel); +#if (PROJDEBUG ==1) + cout << "Save drive usage." << endl; +#endif + parentfs->savedriveusage(); +#if (PROJDEBUG ==1) + cout << "Commit FS" << endl; +#endif + parentfs->commit(); + return RESULT_SUCCESS; +} + +void hd24project::sort() +{ + // a max. of 99 elements is still doable by bubble sort. + int songs=this->songcount(); + if (songs<2) return; // nothing to sort! + string** songnames=(string**)memutils::mymalloc("hd24project::sort",99,sizeof(string*)); + hd24song* song1=NULL; + + int i, j; + int arrayLength = songs; + for (i=1;i<=arrayLength;i++) + { + song1=getsong(i); + songnames[i-1]=song1->songname(); + delete song1; + song1=NULL; + } + + for(i = 1; i <= arrayLength ; i++) + { + for (j=0; j < (arrayLength -1); j++) + { + int compare=strncmp(songnames[j]->c_str(),songnames[j+1]->c_str(),64); + if (compare>0) + { + // swap entries + __uint32 a=getsongsectornum(j+1); + __uint32 b=getsongsectornum(j+2); + setsongsectornum(j+2,a); + setsongsectornum(j+1,b); + string* tmp=songnames[j]; + songnames[j]=songnames[j+1]; + songnames[j+1]=tmp; + } + } + } + + for (i=1;i<=arrayLength;i++) + { + free(songnames[i-1]); + } + free(songnames); + return; +} 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 @@ +#include "hd24sndfile.h" +#include +#include +#include +#include +using std::ofstream; +using std::cout; +using std::endl; +hd24sndfile::hd24sndfile(int p_format,SoundFileWrapper* p_soundfile) +{ + sndfilehandle=(SNDFILE*)NULL; + outfilehandle=(ofstream*)NULL; + _handletype=0; // default is 0=libsndfile, 1=native file + sf_format=p_format; + soundfile=p_soundfile; +} + +hd24sndfile::~hd24sndfile() +{ + //if (sndfilehandle!=NULL) + //{ + // delete sndfilehandle; + //} + //if (outfilehandle!=NULL) + //{ + // /delete outfilehandle; + //} +} + +int hd24sndfile::handletype() +{ + return _handletype; +} + +void* hd24sndfile::handle() +{ + if (_handletype==0) + { + return (void*)sndfilehandle; + } + return (void*)outfilehandle; +} + +void hd24sndfile::handle(SNDFILE* newhandle) +{ + sndfilehandle=newhandle; + _handletype=0; +} + +void hd24sndfile::handle(ofstream* newhandle) +{ + outfilehandle=newhandle; + + _handletype=1; + // TODO: Write empty header (for filling in later) +} + +void hd24sndfile::handle(void* newhandle,int htype) +{ + _handletype=htype; + if (htype==1) { + outfilehandle=(ofstream*)newhandle; + return; + } + + sndfilehandle=(SNDFILE*)newhandle; +} + +void hd24sndfile::open(const char* filename,int filemode,SF_INFO* infoblock,SoundFileWrapper* _soundfile) +{ + _handletype=0; // soundfile + soundfile=_soundfile; + sfinfo=infoblock; + sndfilehandle=soundfile->sf_open(filename,filemode,infoblock); + outfilehandle=NULL; + + if (!sndfilehandle) + { + cout << "Problem opening file with the following specs: " << endl; + cout << "rate=" << infoblock->samplerate << endl; + cout << "frames=" << infoblock->frames << endl; + cout << "channels=" << infoblock->channels << endl; + cout << "sections=" << infoblock->sections << endl; + cout << "seekable=" << infoblock->seekable << endl; + cout << "format=" << infoblock->format << endl; + } +} + +void hd24sndfile::open(const char* filename,int filemode,SF_INFO* infoblock) +{ + _handletype=1; // iostream + sfinfo=infoblock; + sndfilehandle=NULL; + outfilehandle=new ofstream(filename,ios_base::out|ios_base::trunc|ios_base::binary); + + if ((sf_format & 0xFF0000) ==SF_FORMAT_WAV) + { + char buf[44]={ + 'R','I','F','F', 0,0,0,0, 'W','A','V','E', 'f','m','t',' ', + 16,0,0,0, 1,0,1,0, 0,0,0,0, 0,0,0,0, + 3,0,24,0, 'd','a','t','a', 0,0,0,0 + }; + + // samplerate follows + long rate=sfinfo->samplerate; // FIXME: Get proper rate from sfinfo + buf[24]=(char)((rate)%256); + buf[25]=(char)(((rate)>>8)%256); + buf[26]=(char)(((rate)>>16)%256); + buf[27]=(char)(((rate)>>24)%256); + + rate*=3; + buf[28]=(char)((rate)%256); + buf[29]=(char)(((rate)>>8)%256); + buf[30]=(char)(((rate)>>16)%256); + buf[31]=(char)(((rate)>>24)%256); + + outfilehandle->write(buf,44); + return; + + } + + if ((sf_format & 0xFF0000) ==SF_FORMAT_AIFF) + { + char buf[54]={ + 'F','O','R','M', + 0,0,0,0, /* Bytes that follow in this file */ + 'A','I','F','F', 'C','O','M','M', + 0,0,0,18, /* chunksize */ + 0,1, /*numchannels*/ + 0,0,0,0, /*sampleframes */ + 0,24, /* Samplesize in bits */ + 0,0,0,0,0,0,0,0,0,0, /* sample rate as 80 bit IEEE float */ + 'S','S','N','D', + 0,0,0,0, /* sound block datalen, to be filled afterwards */ + 0,0,0,0, /* offset */ + 0,0,0,0 /* blocksize */ /* -> data follows */ + }; + + // samplerate follows + long rate=sfinfo->samplerate; // FIXME: Get proper rate from sfinfo + Convert::setfloat80((unsigned char*)buf,28,rate); + + outfilehandle->write(buf,54); + return; + + } +} +void hd24sndfile::writerawbuf(unsigned char* buf,__uint32 subblockbytes) +{ + if ((sf_format & 0xFF0000) ==SF_FORMAT_AIFF) + { + // and we're doing 24 bits. + for (__uint32 i=0;i16 bit conversion here + + if (sndfilehandle != NULL) + { + #if (HD24DEBUG==1) + cout << "soundfile=" << soundfile <sf_write_raw(sndfilehandle,buf,subblockbytes);" << endl; + #endif + soundfile->sf_write_raw(sndfilehandle,buf,subblockbytes); + return; + } + if (outfilehandle!=NULL) + { + outfilehandle->write((const char*)buf,subblockbytes); + } +} + +void hd24sndfile::close() +{ + if (sndfilehandle != NULL) + { + soundfile->sf_close(sndfilehandle); + return; + } + if (outfilehandle == NULL) return; + + + switch (sf_format & 0xFF0000) + { + case SF_FORMAT_WAV: + { + // TODO: set sample rate, len, etc. in header + long pos=outfilehandle->tellp(); + char bufword[4]; + bufword[0]=(char)((pos-8)%256); + bufword[1]=(char)(((pos-8)>>8)%256); + bufword[2]=(char)(((pos-8)>>16)%256); + bufword[3]=(char)(((pos-8)>>24)%256); + outfilehandle->seekp(4); + outfilehandle->write(bufword,4); + + bufword[0]=(char)((pos-44)%256); + bufword[1]=(char)(((pos-44)>>8)%256); + bufword[2]=(char)(((pos-44)>>16)%256); + bufword[3]=(char)(((pos-44)>>24)%256); + outfilehandle->seekp(40); + outfilehandle->write(bufword,4); + + outfilehandle->close(); + break; + } + case SF_FORMAT_AIFF: + { + long pos=outfilehandle->tellp(); + char bufword[4]; + bufword[3]=(char)((pos-8)%256); + bufword[2]=(char)(((pos-8)>>8)%256); + bufword[1]=(char)(((pos-8)>>16)%256); + bufword[0]=(char)(((pos-8)>>24)%256); + + outfilehandle->seekp(4); + outfilehandle->write(bufword,4); + + long chunksize=(pos-46); + long sambytes=chunksize-8; + + + long samframes=sambytes/3; // Bytes per sample. TODO: Not hardcode this + bufword[3]=(char)(samframes%256); + bufword[2]=(char)((samframes>>8)%256); + bufword[1]=(char)((samframes>>16)%256); + bufword[0]=(char)((samframes>>24)%256); + outfilehandle->seekp(22); + outfilehandle->write(bufword,4); + + + bufword[3]=(char)(chunksize%256); + bufword[2]=(char)((chunksize>>8)%256); + bufword[1]=(char)((chunksize>>16)%256); + bufword[0]=(char)((chunksize>>24)%256); + outfilehandle->seekp(42); + outfilehandle->write(bufword,4); + + + + outfilehandle->close(); + break; + + } + default: + { + outfilehandle->close(); + break; + + } + } +} + +void hd24sndfile::write_float(float* buf,__uint32 frames) +{ + if (sndfilehandle != NULL) + { + soundfile->sf_write_float(sndfilehandle,buf,frames); + } + return; +} + + 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 @@ +#ifndef __hd24sndfile_h__ +#define __hd24sndfile_h__ +class SoundFileWrapper; +#include +#include +using std::ofstream; +#include +#include + +class hd24sndfile +{ +private: + + SF_INFO* sfinfo; + int _handletype; + SoundFileWrapper* soundfile; /* runtime loading wrapper for libsndfile */ + int sf_format; +public: + SNDFILE* sndfilehandle; + ofstream *outfilehandle; + + hd24sndfile(int p_format,SoundFileWrapper* p_soundfile); + ~hd24sndfile(); + int handletype(); + void* handle(); + void handle(SNDFILE* newhandle); + void handle(ofstream* newhandle); + void handle(void* newhandle,int htype); + void open(const char* filename,int filemode,SF_INFO* infoblock, + SoundFileWrapper* _soundfile); + void open(const char* filename,int filemode,SF_INFO* infoblock); + void writerawbuf(unsigned char* buf,__uint32 subblockbytes); + void close(); + void write_float(float* buf,__uint32 frames); +}; + +#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 @@ +#include +#include "hd24fs.h" +#include "convertlib.h" +#include "memutils.h" +#define FRAMESPERSEC 30 /* 30 or 100; 30=default for HD24 (=SMPTE rate) */ +#define SONGDEBUG 0 +#if (SONGDEBUG==1) +#define MEMLEAKMULT 10000 +#else +#define MEMLEAKMULT 1 +#endif +#define CACHEBUFFERS 30 /* enough for 25 locate points+some lookahead */ +#define NOTHINGTOQUEUE 0xFFFFFFFF +#define CACHEBLOCK_UNUSED 0xFFFFFFFF /* a song can never have this number of blocks + because this is the max no. of samples in a song + and a block consists of multiple samples */ +#define SONGINFO_AUDIOBLOCKS 0x00 +#define SONGINFO_SECSAMPLESWITCH 0x8 /* *512=samples before switch to next track */ +#define SONGINFO_SECBYTESWITCH 0xC /* *512=bytes before switch to next track */ +#define SONGINFO_SONGNAME_8 0x28 +#define SONGINFO_CHANNELS 0x31 +#define SONGINFO_SAMPLERATE 0x34 +#define SONGINFO_BITDEPTH 0x37 +#define SONGINFO_SONGLENGTH_IN_SAMPLES 0x38 +#define SONGINFO_WRITEPROTECTED 0x3c +#define SONGINFO_LOCATEPOINTLIST 0xb8 +#define LOCATEENTRY_LENGTH 12 +#define SONGINFO_SONGNAME 0x3b8 +#define SONGINFO_ALLOCATIONLIST 0x400 +#define ALLOCINFO_ENTRYLEN 8 +#define ALLOCINFO_SECTORNUM 0x00 +#define ALLOCINFO_AUDIOBLOCKSINBLOCK 0x04 +#define ALLOC_ENTRIES_PER_SONG (ALLOC_SECTORS_PER_SONG*(512/ALLOCINFO_ENTRYLEN)) +#define LOCATE_TIMECODE 0 +#define LOCATE_NAME 4 +/* Quick calculation: A song is max 2^32 samples * 3 bytes *24 tracks + = 309 237 645 312 bytes + 1 block=0x480h sectors = 589 824 bytes + So the max number of blocks in a song = (309237645312 / 589824) blocks = 524288 blocks +*/ +#define MAX_BLOCKS_IN_SONG 524288 +const int hd24song::LOCATEPOS_SONGSTART =0; +const int hd24song::LOCATEPOS_LOOPSTART =1; +const int hd24song::LOCATEPOS_LOOPEND =2; +const int hd24song::LOCATEPOS_PUNCHIN =21; +const int hd24song::LOCATEPOS_PUNCHOUT =22; +const int hd24song::LOCATEPOS_EDITIN =23; +const int hd24song::LOCATEPOS_EDITOUT =24; +const int hd24song::LOCATEPOS_LAST =24; +const int hd24song::READMODE_COPY =0; +const int hd24song::READMODE_REALTIME =1; +const int hd24song::WRITEMODE_COPY =2; +const int hd24song::WRITEMODE_REALTIME =3; +void hd24song::loadblockintocache(__uint32 blocktoqueue) +{ + __uint32 blocksize_in_sectors=parentfs->getblocksizeinsectors(); + + for (int i=LOCATEPOS_LAST;i= rtallocaudioblocks) { + rtallocentrynum++; // reset cursor to start of song + if (rtallocentrynum>=ALLOC_ENTRIES_PER_SONG ) break; + rtallocstartblock+=rtallocaudioblocks; // blocknum of first block in current allocation entry + rtallocstartsector=Convert::getint32(buffer, + SONGINFO_ALLOCATIONLIST+(ALLOCINFO_ENTRYLEN*rtallocentrynum)+ALLOCINFO_SECTORNUM); + rtallocaudioblocks=Convert::getint32(buffer, + SONGINFO_ALLOCATIONLIST+(ALLOCINFO_ENTRYLEN*rtallocentrynum)+ALLOCINFO_AUDIOBLOCKSINBLOCK); + + } +/////////////////////////////////////////////////// +// cout << "allocentrynum=" << rtallocentrynum << endl; + parentfs->readsectors(parentfs->devhd24, + rtallocstartsector+((blocknum-rtallocstartblock)*blocksize_in_sectors), + cachebuf_ptr[currcachebufnum],blocksize_in_sectors); // raw read + +// cachebuf_ptr[currcachebufnum]=NULL; // TODO: READ SECTORS!!! + + currcachebufnum++; + if (currcachebufnum>=CACHEBUFFERS) + { + currcachebufnum=LOCATEPOS_LAST+1; + } + return; +} + + +void hd24song::bufferpoll() { + // A process can call this procedure to tell the song + // object to check the cache request queue for blocks + // to cache. + if (currentreadmode==READMODE_COPY) return; + if (polling==1) + { + // Previous poll is still in progress. + // This is not a proper semaphore system but will + // help relief processing weight should the system + // get overloaded. Normally bufferpoll shouldn't be + // called much more than around 20 times per second, + // so the chance two polls interfere with one another + // is minimal. + return; + } + polling=1; // semaphore + if (blocktoqueue!=NOTHINGTOQUEUE) + { +// cout << "queue request for " <LOCATEPOS_LAST) return songlength_in_samples(); + long entryoffset=SONGINFO_LOCATEPOINTLIST+(locatepoint*LOCATEENTRY_LENGTH); + return Convert::getint32(buffer,entryoffset+LOCATE_TIMECODE); +} + +string* hd24song::getlocatename(int locatepoint) +{ + if (locatepoint<0) locatepoint=0; + if (locatepoint>LOCATEPOS_LAST) { + string* newstr=new string("END"); + return newstr; + } + long entryoffset=SONGINFO_LOCATEPOINTLIST+(locatepoint*LOCATEENTRY_LENGTH); + return Convert::readstring(buffer,entryoffset+LOCATE_NAME,8); +} + + +void hd24song::setlocatename(int locatepoint,string newname) +{ + + if (locatepoint<0) locatepoint=0; + if (locatepoint>LOCATEPOS_LAST) return; + while (newname.length()<8) { + newname+=" "; + } + long entryoffset=SONGINFO_LOCATEPOINTLIST+(locatepoint*LOCATEENTRY_LENGTH); + for (__uint32 i=0;i<8;i++) { + buffer[entryoffset+LOCATE_NAME+i]=newname.c_str()[i]; + } + return; +} +void hd24song::silenceaudioblocks(__uint32 allocsector,__uint32 numblocks) +{ + /* Given a sector number and a block count, silence the + given number of audio blocks on the drive starting + from the given sector number. + This function has 2 modes- one working with a 1-sector + stack-allocated block (slow), the other working with + a heap-allocated cluster (fast but memory intensive). + The heap method may need up to a few (2.3 or so) megabytes of RAM. + If heap allocation fails, the slow method is used. + */ + unsigned char onesector[512]; + memset(onesector,0,512); + + __uint32 sectorstoclear=parentfs->getblocksizeinsectors(); + sectorstoclear*=numblocks; + unsigned char* clearblock=(unsigned char*)memutils::mymalloc("silenceaudioblocks",sectorstoclear*512,1); + if (clearblock==NULL) + { + // Alloc failed, use low-memory use version + for (__uint32 i=0;iwritesectors(parentfs->devhd24, + allocsector+i, + onesector, + 1); + } + } + else + { + memset(clearblock,0,512*sectorstoclear); + parentfs->writesectors(parentfs->devhd24, + allocsector, + clearblock, + sectorstoclear); + memutils::myfree("silenceaudioblocks",clearblock); + } + return; +} + +bool hd24song::setallocinfo(bool silencenew) +{ + return setallocinfo(silencenew,NULL,NULL,NULL); +} + +__uint32 hd24song::requiredaudioblocks(__uint32 songlen) +{ + /* Figure out how many audio blocks we would expect + the song to have based on the songlength in samples. */ + __uint32 blocksize_in_sectors=parentfs->getblocksizeinsectors(); + __uint32 blocksize_in_bytes=blocksize_in_sectors*SECTORSIZE; + __uint32 bits=(this->bitdepth()); + __uint32 bytes_per_sample=bits/8; + __uint32 tracks_per_song=physical_channels(); + __uint32 tracksamples_per_block=0; + if (tracks_per_song>0) { + tracksamples_per_block=(blocksize_in_bytes / bytes_per_sample) / tracks_per_song; + } + + __uint32 remainder=songlen%tracksamples_per_block; + __uint32 blocks_expected=(songlen-remainder)/tracksamples_per_block; + if (remainder!=0) { + blocks_expected++; + } + return blocks_expected; +} + +bool hd24song::allocatenewblocks(__uint32 blockstoalloc,bool silencenew,char* message,int* cancel,int (*checkfunc)()) +{ + /* Allocate space in the real drive usage table. + Mind that we've been asked to allocate a certain + number of blocks, although in reality we are not + allocating blocks but clusters of blocks. */ +#if (SONGDEBUG == 1) + cout << "Total blocks to alloc=" << blockstoalloc << endl; +#endif + __uint32 totblockstoalloc=blockstoalloc; + __uint32 allocsector=0; + __uint32 blockspercluster=parentfs->getblockspercluster(); + cancel=cancel; + while (blockstoalloc>0) + { + __uint32 pct=(__uint32)((100*(totblockstoalloc-blockstoalloc))/totblockstoalloc); + if (message!=NULL) { + sprintf(message, + "Lengthening song... allocating block %ld of %ld, %ld%% done", + (long)(totblockstoalloc-blockstoalloc), + (long)totblockstoalloc, + (long)pct + ); + } + if (checkfunc!=NULL) + { + checkfunc(); + } + allocsector=getnextfreesector(allocsector); + +#if (SONGDEBUG == 1) + cout << "Allocsector=" << allocsector << endl; + cout << "Blockstoalloc=" << blockstoalloc << endl; +#endif + if (allocsector==0) { +#if (SONGDEBUG == 1) + cout << "Ran out of space with " << blockstoalloc + <<" left to alloc " << endl; +#endif + + return false; + } + if (silencenew) + { + // overwrite cluster with silence. +#if (SONGDEBUG == 1) + cout << "Overwriting cluster with silence." << endl; +#endif + this->silenceaudioblocks(allocsector,blockspercluster); + } + __uint32 alloccluster=parentfs->sector2cluster(allocsector); +#if (SONGDEBUG == 1) + cout << "Alloccluster=" << alloccluster << endl; +#endif + parentfs->enablebit(alloccluster,parentfs->sectors_driveusage); + if (blockstoalloc>=blockspercluster) + { + blockstoalloc-=blockspercluster; + } + else + { + blockstoalloc=0; + } + } + return true; +} + +bool hd24song::setallocinfo(bool silencenew,char* message,int* cancel,int (*checkfunc)()) +{ + /* This function is intended for recovering live recordings + and lengthening songs. To use it, set a new song length + first, then call this function- it will add the required + number of blocks to the song. + + Boolean 'silencenew' indicates if newly allocated space + should be overwritten with silence. + + For initializing songs to nonzero length, you will want + to set this to TRUE. + + For recovering live recordings you will want to set it + to FALSE. + + For realtime recording, it is set to FALSE for efficiency + reasons, as the recording algorithm itself will overwrite + newly allocated space with audio (and silence as needed). + + Savemessage allows giving textual feedback to the user + and the int pointed to by cancel will be set to 1 by the + GUI if the user interrupts the process. + In case of recovering a song, after setting the length of + a crashed song to the estimated duration, we want to try + to find back the audio. + + It is reasonable that this previously recorded audio can be + found by simply allocating as many unused clusters to the + song as needed to reach the desired length; because those + same clusters would have been allocated to the song after + pressing 'stop'. + + This function attempts to perform this allocation (which + should also allow people to perform headerless + live recoveries). + + The way this will work is: + -- find out how many audio blocks are allocated to the song; + -- find out how many we think there *should* be allocated; + -- then, allocate those blocks (in a copy of the usage table); + -- finally, append the newly allocated blocks to the song. + -- the last can be done by subtracting the old usage table + from the new one and calling appendorphanclusters. + + FIXME: operation is not correct when running out of drive space. + TODO: we count blocks to allocate but in reality clusters are + being reserved. Shouldn't we work cluster based all the + way? + */ + + __uint32 blocksinalloctable=audioblocks_in_alloctable(); + __uint32 blocks_expected=requiredaudioblocks(songlength_in_samples()); + + +#if (SONGDEBUG == 1) + cout << "Actual blocks allocated for song:" << blocksinalloctable << endl; + cout << "Expected blocks allocated for song:" << blocks_expected << endl; +#endif + if (blocksinalloctable==blocks_expected) + { + // right amount of space is already allocated. + return true; + } + + if (blocksinalloctable>blocks_expected) + { + // looks like too much space is allocated, + // but setallocinfo() won't support song shrinking + // for now. + return false; + } + + /* Not enough space is allocated-- allocate as much extra as needed. */ +#if (SONGDEBUG == 1) + cout << "Allocating space for song. " <getcopyofusagetable(); + if (copyusagetable==NULL) + { + /* Cannot get usage table (out of memory?) */ + return false; + } + + bool tryallocnew=this->allocatenewblocks(blockstoalloc,silencenew,message,cancel,checkfunc); + if (tryallocnew==false) + { + /* Cannot allocate new blocks (out of drive space?) */ + memutils::myfree("copyusagetable",copyusagetable); + return false; + } + + /* Cluster allocation succeeded. + To find out which clusters have been allocated, + XOR the previous copy of the usage table over it. + This will result in a list of newly allocated + (orphan) clusters still to be appended to the song. + */ + for (__uint32 i=0;i<(512*15);i++) + { + copyusagetable[i]=(copyusagetable[i]) + ^(parentfs->sectors_driveusage[i]); + } + +#if (SONGDEBUG == 1) + cout << "Alloc action successful- append orphan clusters now." << endl; +#endif + // call appendorphanclusters + if (message!=NULL) + { + sprintf(message,"Adding allocated space to song..."); + if (checkfunc!=NULL) + { + checkfunc(); + } + } + bool songresize; + if (silencenew) { + songresize=false; + } + else + { + songresize=true; + } + appendorphanclusters(copyusagetable,songresize); + memutils::myfree("copyusagetable",copyusagetable); + // save for either song or drive usage table is not + // to be called here- it would violate the concept + // of safe, read-only recovery. + return true; +} + +void hd24song::appendorphanclusters(unsigned char* usagebuffer,bool allowsongresize) +{ + __uint32 clusters=parentfs->clustercount(); + __uint32 currpos=0; + __uint32 curralloctableentry=used_alloctable_entries(); +#if (SONGDEBUG == 1) + cout << "Appending orphan clusters to song. Used alloctable entries=" << curralloctableentry + << "clusters=" << clusters + << endl; +#endif + + while (currposisfreecluster(blockstart,usagebuffer) && (blockstartisfreecluster(blockend,usagebuffer) && (blockendcluster2sector(blockstart)); + __uint32 entrynumblocks=(unsigned int)( parentfs->getblockspercluster()*blocklen ); + Convert::setint32(buffer, + SONGINFO_ALLOCATIONLIST+ALLOCINFO_SECTORNUM + +(ALLOCINFO_ENTRYLEN*curralloctableentry),entrystartsector); + + Convert::setint32(buffer, + SONGINFO_ALLOCATIONLIST+ALLOCINFO_AUDIOBLOCKSINBLOCK + +(ALLOCINFO_ENTRYLEN*curralloctableentry),entrynumblocks); + curralloctableentry++; +#if (SONGDEBUG == 1) + printf("%x %x\n",(unsigned int)parentfs->cluster2sector(blockstart),(unsigned int)( parentfs->getblockspercluster()*blocklen )); +#endif + } + /* the operation may have resulted in the song getting + longer. This is due to the fact that while recording, + 'stop' may be pressed before all audio blocks of the + cluster have been used. + Also, of course, there may be more orphaned clusters + around than belong to the song- for whatever reason. + */ + + __uint32 blocksinalloctable=audioblocks_in_alloctable(); + + __uint32 blocksize_in_sectors=parentfs->getblocksizeinsectors(); + __uint32 blocksize_in_bytes=blocksize_in_sectors*SECTORSIZE; + __uint32 bits=(this->bitdepth()); + __uint32 bytes_per_sample=bits/8; + __uint32 tracks_per_song=physical_channels(); + __uint32 tracksamples_per_block=0; + if (tracks_per_song>0) { + tracksamples_per_block=(blocksize_in_bytes / bytes_per_sample) / tracks_per_song; + } + __uint32 newsonglen=tracksamples_per_block*blocksinalloctable; + Convert::setint32(buffer,SONGINFO_AUDIOBLOCKS,blocksinalloctable); + + /* The following directly sets the songlength in the song buffer + rather than via songlength_in_samples(val) to prevent + testing whether more space needs to be allocated- + which is not needed as space has just been allocated. + (Also, the below number may be less accurate than the + number some user might specify via songlength_in_samples(val)). + */ + if (allowsongresize) + { + Convert::setint32(buffer,SONGINFO_SONGLENGTH_IN_SAMPLES,newsonglen); + } + return; +} + +void hd24song::setblockcursor(__uint32 blocknum) +{ + allocentrynum=0; // reset cursor to start of song + allocstartblock=0; // blocknum of first block in current allocation entry + allocstartsector=Convert::getint32(buffer,SONGINFO_ALLOCATIONLIST+(ALLOCINFO_ENTRYLEN*allocentrynum)+ALLOCINFO_SECTORNUM); + allocaudioblocks=Convert::getint32(buffer,SONGINFO_ALLOCATIONLIST+(ALLOCINFO_ENTRYLEN*allocentrynum)+ALLOCINFO_AUDIOBLOCKSINBLOCK); + // cout << " allocaudioblocks=" << allocaudioblocks << endl; + while ((blocknum-allocstartblock) >= allocaudioblocks) { + allocentrynum++; // reset cursor to start of song + allocstartblock+=allocaudioblocks; // blocknum of first block in current allocation entry + allocstartsector=Convert::getint32(buffer, + SONGINFO_ALLOCATIONLIST+(ALLOCINFO_ENTRYLEN*allocentrynum)+ALLOCINFO_SECTORNUM); + allocaudioblocks=Convert::getint32(buffer, + SONGINFO_ALLOCATIONLIST+(ALLOCINFO_ENTRYLEN*allocentrynum)+ALLOCINFO_AUDIOBLOCKSINBLOCK); + } + return; +} + +void hd24song::unmark_used_clusters(unsigned char* sectors_inuse) +{ + /* + * Given an image of used clusters, this function + * will alter that image to unmark the clusters + * in use by this song. + * Under normal circumstances, this is used to + * delete songs. + * However, it is also useful to search for orphan + * clusters (by unmarking all clusters in use by + * all songs- the remaining clusters then must be + * orphan clusters) + */ +#if (SONGDEBUG == 1) + cout << "unmark used clusters." << endl; +#endif + __uint32 allocentries=used_alloctable_entries(); + + if (allocentries==0) { +#if (SONGDEBUG == 1) + cout << "Song claims no used allocation entries." << endl; +#endif + return; + } + + __uint32 blockspercluster=parentfs->getblockspercluster(); + + for (__uint32 i=0; isector2cluster(entrystartsector); +#if (SONGDEBUG == 1) + cout << "startsector=" <freecluster(clust2free,sectors_inuse); +#if (SONGDEBUG == 1) + cout << clust2free << " "; +#endif + } +#if (SONGDEBUG == 1) + cout << endl; +#endif + } +} + +__uint32 hd24song::currentlocation() +{ + return songcursor; +} +void hd24song::currentlocation(__uint32 offset) +{ + golocatepos(offset); +} + +__uint32 hd24song::golocatepos(__uint32 offset) +{ + /* Offset indicates next sample that will be + played back (or recorded). A song of 1 sample long + can have the cursor set at offset 0 or offset 1; + offset 1 is then beyond the end of the song, which is + meaningful for recording but not for playback. */ + + __uint32 songlen=songlength_in_samples(); + + if (offset>songlen) { + offset=songlen; + //return offset; + } + + songcursor=offset; + evenodd=0; + + __uint32 samplenumber=songcursor; +#if (SONGDEBUG == 1) +// cout << "songcursor=" << songcursor << endl; +#endif + __uint32 blocksize_in_sectors=parentfs->getblocksizeinsectors(); + __uint32 blocksize_in_bytes=blocksize_in_sectors*SECTORSIZE; + __uint32 bits=(this->bitdepth()); + __uint32 bytes_per_sample=bits/8; + __uint32 tracks_per_song=physical_channels(); + __uint32 tracksamples_per_block=0; + if (tracks_per_song>0) { + tracksamples_per_block=(blocksize_in_bytes / bytes_per_sample) / tracks_per_song; + } + __uint32 blocknum=0; + if (tracksamples_per_block>0) { + blocknum=(samplenumber/(tracksamples_per_block)); + } + +#if (SONGDEBUG == 1) +// cout << "still going strong" << endl; +#endif + + setblockcursor(blocknum); + + return songcursor; +} + +__uint32 hd24song::setlocatepos(int locatepoint,__uint32 offset) +{ + /** Sets the value of a locate point to the given offset. + Parameters: + locatepoint + The 0-based locate point identifier + offset + The new offset (in samples*) for the locate point. + * In high samplerate songs (88k2, 96k), the offset is given as + number of sample pairs, because audio data is interlaced + across 2 physical tracks. + */ + + if (locatepoint<0) + { + locatepoint=0; + } + + if (locatepoint>LOCATEPOS_LAST) + { + return 0; + } + + long entryoffset=SONGINFO_LOCATEPOINTLIST + +(locatepoint*LOCATEENTRY_LENGTH); + + buffer[entryoffset+LOCATE_TIMECODE+3]=offset%256; + offset=offset>>8; + buffer[entryoffset+LOCATE_TIMECODE+2]=offset%256; + offset=offset>>8; + buffer[entryoffset+LOCATE_TIMECODE+1]=offset%256; + offset=offset>>8; + buffer[entryoffset+LOCATE_TIMECODE+0]=offset%256; + return getlocatepos(locatepoint); +} + +hd24song::hd24song(hd24project* p_parent,__uint32 p_songid) +{ +#if (SONGDEBUG == 1) + cout << "CONSTRUCT hd24song " << p_songid << endl; +#endif + currentreadmode=READMODE_COPY; + blocktoqueue=NOTHINGTOQUEUE; + polling=0; + evenodd=0; + audiobuffer=NULL; + scratchbook=NULL; + buffer=NULL; + framespersec=FRAMESPERSEC; + lastallocentrynum=0; + busyrecording=false; + mysongid=p_songid; + rehearsemode=false; + lengthened=false; + lastavailablecacheblock=0xFFFFFFFF; + currcachebufnum=LOCATEPOS_LAST+1; + buffer=(unsigned char*)memutils::mymalloc("hd24song-buffer",16384,1); + parentfs=p_parent->parentfs; + parentproject=p_parent; + __uint32 blocksize_in_sectors=parentfs->getblocksizeinsectors(); + __uint32 blocksize_in_bytes=blocksize_in_sectors*SECTORSIZE; + + for (__uint32 tracknum=1;tracknum<=24;tracknum++) + { + track_armed[tracknum-1]=false; + } + + // 'read enabled' is used in copy mode to reduce the amount of + // secors that need to be read from disk. + for (__uint32 tracknum=1;tracknum<=24;tracknum++) + { + track_readenabled[tracknum-1]=true; // by default all are read enabled. + } + +#if (SONGDEBUG == 1) + cout << "2" << endl; +#endif + audiobuffer=(unsigned char *)memutils::mymalloc("hd24song-audiobuffer",blocksize_in_bytes+SECTORSIZE,1); + scratchbook=(unsigned char *)memutils::mymalloc("hd24song-scratchbook",blocksize_in_bytes+SECTORSIZE,1); + + if (audiobuffer==NULL) { +#if (SONGDEBUG ==1) + cout << "could not allocate audio buffer" << endl; +#endif + } + + // Set up cache buffers for realtime access + // first, dynamically create pointer array + cachebuf_blocknum=(__uint32*)memutils::mymalloc("hd24song-cachebuf",sizeof(__uint32)*CACHEBUFFERS,1); + cachebuf_ptr=(unsigned char**)memutils::mymalloc("hd24song-cachebufptr",sizeof (unsigned char *)*CACHEBUFFERS,1); + // then, allocate blocks and point array to it. + int i; + + for (i=0;igetsongsectornum(mysongid); +#if (SONGDEBUG ==1) + cout << "Reading # song sectors= " << TOTAL_SECTORS_PER_SONG + << "from sec " << songsector << endl; +#endif + parentfs->readsectors(parentfs->devhd24, + songsector, + buffer,TOTAL_SECTORS_PER_SONG); + parentfs->fstfix(buffer,TOTAL_SECTORS_PER_SONG*512); + //ncout << "sectors read="<mysongid; +} + +bool hd24song::has_unexpected_end() +{ + // Check if this song has an 'unexpected end of song' error + // (in header mode, this always returns false) + if (this->parentfs->headersectors!=0) + { + return false; + } + // find out how many audioblocks are claimed to be allocated in the + // song allocation info table + + __uint32 blocksinalloctable=audioblocks_in_alloctable(); + + if ( blocksinalloctable < Convert::getint32(buffer,SONGINFO_AUDIOBLOCKS) ) + { + // the song itself claims it should have more audioblocks + return true; + } + // Over here we could also verify the expected number of blocks + // against the given song length in samples. + return false; +} + +bool hd24song::is_fixable_unexpected_end() +{ + /** Checks if this song has a FIXABLE 'unexpected end of song' error */ + __uint32 blocksinalloctable=audioblocks_in_alloctable(); +#if (SONGDEBUG == 1) + cout << "Blocks in alloctable=" << blocksinalloctable << endl; +#endif + __uint32 songblockcount=Convert::getint32(buffer,SONGINFO_AUDIOBLOCKS); + if (songblockcount>MAX_BLOCKS_IN_SONG) + { + /* Safety feature: corruption detected, + block count of song is greater than theoretical maximum. */ + songblockcount=MAX_BLOCKS_IN_SONG; + } + + /* Values in songblockcount and blocksinalloctable should be equal + unless the song is corrupt. If the latter value lower, + there is an 'unexpected end of song' error. */ + + if (!( blocksinalloctable < songblockcount )) + { + // No unexpected end of song error, nothing to fix + return false; + } + + /* There is an unexpected end of song error. But is it one of + the type we know how to automatically fix? */ + + if (used_alloctable_entries() == (512/ALLOCINFO_ENTRYLEN) ) { + /* Yes, it is. We have exactly 1 sector of allocated data and + the rest is zero data, due to a known (presumed) bug in + the HD24 recorder. */ + return true; + } + + /* No, it isn't. Then assume we cannot fix it. */ + return false; +} + +__uint32 hd24song::used_alloctable_entries() +{ + /** Counts how many entries in the song allocation table + are in use. */ + __uint32 MAXALLOCENTRIES=((512/ALLOCINFO_ENTRYLEN)*5)-1; + + for (__uint32 i=0;iMAX_BLOCKS_IN_SONG) + { + /* Safety net: Corruption detected, song claims to use + more blocks than the theoretical possible maximum. */ + return MAX_BLOCKS_IN_SONG; + } + } + + return totblocks; +} + +hd24song::~hd24song() +{ +#if (SONGDEBUG == 1) + cout << "DESTRUCT hd24song " << mysongid << endl; +#endif + if (buffer!=NULL) + { + memutils::myfree("buffer",buffer); + buffer=NULL; + } + if (scratchbook != NULL) + { + memutils::myfree("scratchbook",scratchbook); + scratchbook=NULL; + } + if (audiobuffer != NULL) + { + memutils::myfree("audiobuffer",audiobuffer); + audiobuffer=NULL; + } + if (blocksector != NULL) + { + memutils::myfree("blocksector",blocksector); + blocksector=NULL; + } + int i; + + // clear cache + for (i=0;iversion(); + if (*ver == "1.00") { + // version 1.0 filesystem. + delete ver; + string* tmp=new string(""); + string* dummy=Convert::readstring(songbuf,SONGINFO_SONGNAME_8,8); + + *tmp+=*dummy; + delete dummy; + if (tmp->length()==8) { + dummy=Convert::readstring(songbuf,SONGINFO_SONGNAME_8+10,2); + *tmp+=*dummy; + delete dummy; + } + return tmp; + } + delete ver; + string* tmp=Convert::readstring(songbuf,SONGINFO_SONGNAME,64); + return tmp; +} + +string* hd24song::songname() +{ + return songname(this->parentfs,buffer); +} + +void hd24song::songname(string newname) +{ + songname(buffer,newname); +} + +void hd24song::songname(unsigned char* songbuf,string newname) +{ + hd24fs::setname(songbuf,newname,SONGINFO_SONGNAME_8,SONGINFO_SONGNAME); + return; +} + +bool hd24song::iswriteprotected() +{ + __uint32 writeprot=(Convert::getint32(buffer,SONGINFO_WRITEPROTECTED)); + writeprot&=0x04000000; + if (writeprot==0) return false; + return true; +} + +void hd24song::setwriteprotected(bool prot) +{ + __uint32 writeprot=(Convert::getint32(buffer,SONGINFO_WRITEPROTECTED)); + writeprot&=0xFBFFFFFF; + + if (prot) { + writeprot|=0x04000000; + } + Convert::setint32(buffer,SONGINFO_WRITEPROTECTED,writeprot); + return; +} + +void hd24song::physical_channels(unsigned char* songbuf,__uint32 newchannelcount) +{ + if (newchannelcount>24) newchannelcount=24; + songbuf[SONGINFO_CHANNELS]=(unsigned char)(newchannelcount&0xFF); +} + +void hd24song::physical_channels(__uint32 newchannelcount) +{ + physical_channels(buffer,newchannelcount); +} + +__uint32 hd24song::physical_channels(unsigned char* songbuf) +{ + int channels=Convert::getint32(songbuf,SONGINFO_CHANNELS)>>24; + channels=(channels & 0x1f); + if (channels>24) channels=24; + return channels; +} + +__uint32 hd24song::physical_channels() +{ + return physical_channels(buffer); +} + +__uint32 hd24song::logical_channels() +{ + if (this->samplerate()>=88200) + { + return (physical_channels()>>1); + } else { + return (physical_channels()); + } +} + +__uint32 hd24song::logical_channels(unsigned char* songbuf) +{ + if (samplerate(songbuf)>=88200) + { + return (physical_channels(songbuf)>>1); + } else { + return (physical_channels(songbuf)); + } +} + +void hd24song::logical_channels(unsigned char* songbuf,__uint32 channelcount) +{ + if (samplerate(songbuf)>=88200) { + physical_channels(songbuf,channelcount*2); + } else { + physical_channels(songbuf,channelcount); + } +} + +__uint32 hd24song::samplerate(unsigned char* songbuf) +{ + __uint32 samrate=Convert::getint32(songbuf,SONGINFO_SAMPLERATE)>>8; + return samrate; +} + +__uint32 hd24song::samplerate() +{ + return samplerate(buffer); +} + +void hd24song::samplerate(unsigned char* songbuf,__uint32 newrate) +{ + __uint32 samrate=(newrate<<8); + __uint32 bd=((unsigned char)songbuf[SONGINFO_BITDEPTH]); + samrate|=bd; + Convert::setint32(songbuf,SONGINFO_SAMPLERATE,samrate); +} + +void hd24song::samplerate(__uint32 newrate) +{ + samplerate(buffer,newrate); +} + + +__uint32 hd24song::bitdepth() +{ + __uint32 depth=(__uint32)((unsigned char)buffer[SONGINFO_BITDEPTH]); + if ((depth!=24) && (depth !=16) && (depth!=32)) return 24; + return depth; +} + +__uint32 hd24song::songlength_in_samples() +{ + return (Convert::getint32(buffer,SONGINFO_SONGLENGTH_IN_SAMPLES)); +} + +__uint32 hd24song::songlength_in_samples(__uint32 newlen,bool silencenew) +{ + return hd24song::songlength_in_samples(newlen,silencenew,NULL,NULL); +} + +__uint32 hd24song::songlength_in_samples(__uint32 newlen,bool silencenew,char* savemessage,int* cancel) +{ + return hd24song::songlength_in_samples(newlen,silencenew,savemessage,cancel,NULL); +} + +hd24fs* hd24song::fs() +{ + return this->parentfs; +} + +__uint32 hd24song::songlength_in_samples(__uint32 newlen,bool silencenew,char* savemessage,int* cancel,int (*checkfunc)()) +{ + /* Sets the length of a song and updates any allocation + info as needed. + The return value of the function is the actual song length + set. Return value may differ from newlen if not enough drive + space was available or if allocating ran into problems + otherwise. */ + if (this==NULL) + { +#if (SONGDEBUG==1) + cout << "Song object is NULL! Cannot lengthen song." << endl; +#endif + return 0; + } + __uint32 oldlen=songlength_in_samples(); + if (savemessage!=NULL) + { + // clear default save message + savemessage[0]='\0'; + } + if (cancel!=NULL) + { + *cancel=0; + } +#if (SONGDEBUG==1) + cout << "Lengthening song to " << newlen << " samples" << endl; + if (silencenew) { + cout << "(And silencing new blocks)" << endl; + } +#endif + Convert::setint32(buffer,SONGINFO_SONGLENGTH_IN_SAMPLES,newlen); + if (newlen==0) { + Convert::setint32(buffer,SONGINFO_AUDIOBLOCKS,0); + return 0; + } + + // the above is required by setallocinfo + if (setallocinfo(silencenew,savemessage,cancel,checkfunc)) { + // setting alloc info succeeded +#if (SONGDEBUG==1) + cout << "Success lengthening song to " << newlen << " samples" << endl; +#endif + this->lengthened=true; + memoizeblocksectors(Convert::getint32(buffer,SONGINFO_AUDIOBLOCKS)); + return newlen; + } + // setting new length failed- reset song to old length. +#if (SONGDEBUG==1) + cout << "Failed. Keep at old length of " <=88200) { samrate=samrate>>1; } + __uint32 cutsonglen=offset-display_subseconds(offset,samrate); + __uint32 totsongsecs=(cutsonglen/samrate); + __uint32 viewsongsecs=totsongsecs%60; + return viewsongsecs; +} + +__uint32 hd24song::display_subseconds() { + return display_subseconds(songlength_in_samples()); +} + +__uint32 hd24song::display_subseconds(__uint32 offset,__uint32 samrate) +{ + if (samrate==0) + { + return 0; + } + if (samrate>=88200) { samrate=samrate>>1; } + __uint32 totsonglen=offset; + __uint32 songsubsecs=totsonglen%samrate; + return songsubsecs; +} + +__uint32 hd24song::display_hours(__uint32 offset) +{ + return display_hours(offset,samplerate()); +} + +__uint32 hd24song::display_minutes(__uint32 offset) +{ + return display_minutes(offset,samplerate()); +} + +__uint32 hd24song::display_seconds(__uint32 offset) +{ + return display_seconds(offset,samplerate()); +} + +__uint32 hd24song::display_subseconds(__uint32 offset) +{ + return display_subseconds(offset,samplerate()); +} + +unsigned char* hd24song::getcachedbuffer(__uint32 blocknum) +{ + // This will return a pointer to an audio buffer containing + // the audio of the given blocknum, if available. + // If not available, it will return a pointer to a silent + // block and queue the blocknum for caching + int i; + bool foundbuf=false; + unsigned char* bufptr=NULL; + + /* A straight loop isn't the fastest way to find the + * correct buffer (a binary tree or hash would perform + * better). However the advantage for a total of around + * 40 blocks (25 locate points and some lookahead) + * would be rather marginal. */ + + bool havenext=false; + bool haveprev=false; + + for (i=LOCATEPOS_LAST;i0) { + if (cachebuf_blocknum[i]==(blocknum-1)) { + haveprev=true; + if (havenext && foundbuf) break; + } + } + if (cachebuf_blocknum[i]==(blocknum+1)) { + havenext=true; + if (haveprev && foundbuf) break; + } + if (cachebuf_blocknum[i]==blocknum) + { + bufptr=cachebuf_ptr[i]; + foundbuf=true; + if (havenext && haveprev) break; + } + } + if (!(foundbuf)) + { + if (!haveprev) + { + queuecacheblock(blocknum-1); + } + if (!havenext) + { + queuecacheblock(blocknum+1); + } + queuecacheblock(blocknum); + return NULL; + } + if (!haveprev) + { + queuecacheblock(blocknum-1); + } + if (!havenext) + { + queuecacheblock(blocknum+1); + } + // Cache buffer was found. + // If we want we can optimize the cache here. + // Otherwise, just return the buffer pointer. + lastavailablecacheblock=blocknum; + return bufptr; +} + +void hd24song::memoizeblocksectors(__uint32 number_of_blocks) +{ + __uint32 totblocksfound=0; + __uint32 myallocentrynum=0; + + __uint32 entrystartsector=0; + __uint32 entrynumblocks=0; + + __uint32 blocksize_in_sectors=parentfs->getblocksizeinsectors(); + + while ( + (totblocksfound < number_of_blocks) + && (totblocksfound <= MAX_BLOCKS_IN_SONG) + && (myallocentrynummaintenancemode==1) { + readmode=hd24song::READMODE_COPY; + } + switch (readmode) + { + case hd24song::READMODE_COPY: + if ((lastreadblock!=blocknum)||(mustreadblock==1)) + { + mustgetaudiodata=true; + } + break; + case hd24song::READMODE_REALTIME: + mustgetaudiodata=false; + if ((lastavailablecacheblock!=blocknum)||(mustreadblock==1)) { + mustgetaudiodata=true; + } + break; + default: + mustgetaudiodata=false; + break; + } + +#if (SONGDEBUG==1) + cout << "readmtsample MARK2" << endl; +#endif + if (mustgetaudiodata) + { + // We advanced a block. This means we need to read more audio data. + // (or in case of realtime reading, at least find out what next block to get) + if (blocknum==(allocstartblock+allocaudioblocks)) + { + // In fact, we've read all data in the current allocation entry. + allocentrynum++; // reset cursor to start of song + allocstartblock=blocknum; // blocknum of first block in current allocation entry + allocstartsector=Convert::getint32(buffer, + SONGINFO_ALLOCATIONLIST+(ALLOCINFO_ENTRYLEN*allocentrynum)+ALLOCINFO_SECTORNUM); + allocaudioblocks=Convert::getint32(buffer, + SONGINFO_ALLOCATIONLIST+(ALLOCINFO_ENTRYLEN*allocentrynum)+ALLOCINFO_AUDIOBLOCKSINBLOCK); + } + + switch (readmode) + { + case (hd24song::READMODE_COPY): + if (parentfs->maintenancemode==1) + { + // in maintenance mode, we will display the sector currently + // being played back (that is what maintenance mode is all + // about + + string* bla=Convert::int32tohex(allocstartsector+((blocknum-allocstartblock)*blocksize_in_sectors)); + cout << *bla << "-1" << endl; // maintenance mode + delete bla; + } + + parentfs->readsectors(parentfs->devhd24, + allocstartsector+((blocknum-allocstartblock)*blocksize_in_sectors), + audiobuffer,blocksize_in_sectors); // raw audio read, no fstfix needed + mustreadblock=0; + break; + case (hd24song::READMODE_REALTIME): + buffertouse=getcachedbuffer(blocknum); + + default: break; + } + // cout << "read done. " << endl; + } +#if (SONGDEBUG==1) + cout << "readmtsample MARK 3" << endl; + cout << "audiobuffer=" << audiobuffer << endl; + cout << "readmtsample MARK 3b" << endl; +#endif + + int sample_within_block=samplenumber%(tracksamples_per_block); + if (readmode==hd24song::READMODE_COPY) + { + buffertouse=audiobuffer; + } + __uint32 trackspersam; + if (samrate>=88200) { + trackspersam=2; + } else { + trackspersam=1; + } +#if (SONGDEBUG==1) + cout << "readmtsample MARK 3c" << endl; +#endif + __uint32 tottracks=logical_channels(); + for (__uint32 tracknum=0;tracknum=88200) + { + // only for high sample rate mode: + evenodd=1-evenodd; + if (evenodd==0) { + songcursor++; + } + } else { + songcursor++; + } + + return; +} + +int hd24song::getmtrackaudiodata(__uint32 firstsamnum,__uint32 samples,unsigned char* buffer,int readmode) +{ + /* WARNING: For best performance the number of samples must not cross + audio block boundaries. This function has been tested in such a fashion only. + + This procedure is intended for reading audio data from disk, + in a completely random access fashion. + It assumes single track audio and will always read only whole blocks, + directly to the given buffer. Return value is a pointer to the + first sample that was supposed to be read. + + The buffer should be sufficiently large to hold the total audio size. + (number of samples*3 bytes for normal sample rates or + number of samples*3*2 bytes for high sample rates (88k2, 96k). + + In copy mode, only required blocks will be read from disk + (no caching will take place- we'll leave this to the OS) + + Realtime mode guarantees to return a result in a short amount of time, + by using a cache. This makes it suitable for realtime playback. + REALTIME MODE IS NOT IMPLEMENTED YET. + When a block is not available in cache, silence is returned. This makes + realtime mode unsuitable for accurate transfers, but suitable for direct + from-disk mixing. Blocks that are not available in cache are queued for + caching. Periodic background checks should be performed on this queue to + help guarantee availability of the blocks to cache. + */ + + currentreadmode=readmode; + __uint32 blocksize_in_sectors=parentfs->getblocksizeinsectors(); + __uint32 blocksize_in_bytes=blocksize_in_sectors*SECTORSIZE; + + __uint32 bits=(this->bitdepth()); + __uint32 bytes_per_sample=bits/8; + __uint32 tracks_per_song=logical_channels(); + __uint32 tracksamples_per_block=(blocksize_in_bytes / bytes_per_sample) / tracks_per_song; + + __uint32 startblocknum=((firstsamnum-(firstsamnum%tracksamples_per_block))/(tracksamples_per_block)); + __uint32 lastsamnum=firstsamnum+samples-1; + __uint32 endblocknum=((lastsamnum-(lastsamnum%tracksamples_per_block))/(tracksamples_per_block)); + + // check read enable flags to allow reducing number of sectors to be transferred. + __uint32 first_readenabled=0; + __uint32 last_readenabled=23; + for (__uint32 i=0;i0;i--) + { + if (track_readenabled[i-1]) + { + last_readenabled=i-1; + break; + } + } +#if (SONGDEBUG==1) + cout << "first,last track="<readsectors(parentfs->devhd24, + blocksector[blocknum]+sectoroffset, + &buffer[firsttrackoffset], + readlength); // raw audio read, no fstfix needed + } + return firstsamnum%tracksamples_per_block; +} + +void hd24song::interlaceblock(unsigned char* sourcebuffer,unsigned char* targetbuffer) +{ + /* This is needed for high sample rates as high sample rate recordings + take up two physical channels for each logical audio channel */ + __uint32 blocksize_in_sectors=parentfs->getblocksizeinsectors(); + __uint32 blocksize_in_bytes=blocksize_in_sectors*SECTORSIZE; + __uint32 blocksize_doubleblock=blocksize_in_bytes/logical_channels(); + __uint32 blocksize_halfblock=blocksize_in_bytes/physical_channels(); + + __uint32 bits=(this->bitdepth()); + __uint32 bytes_per_sample=bits/8; + __uint32 tracksamples_per_halfblock=(blocksize_halfblock/bytes_per_sample); + __uint32 choffset=0; + for (__uint32 ch=0;chgetblocksizeinsectors(); + __uint32 blocksize_in_bytes=blocksize_in_sectors*SECTORSIZE; + __uint32 blocksize_doubleblock=blocksize_in_bytes/logical_channels(); + __uint32 blocksize_halfblock=blocksize_in_bytes/physical_channels(); + + __uint32 bits=(this->bitdepth()); + __uint32 bytes_per_sample=bits/8; + __uint32 tracksamples_per_halfblock=(blocksize_halfblock/bytes_per_sample); + __uint32 choffset=0; + for (__uint32 ch=0;chgetblocksizeinsectors(); + __uint32 blocksize_in_bytes=blocksize_in_sectors*SECTORSIZE; + + __uint32 bits=(this->bitdepth()); + __uint32 bytes_per_sample=bits/8; + __uint32 tracks_per_song=logical_channels(); + __uint32 tracksamples_per_block=(blocksize_in_bytes / bytes_per_sample) / tracks_per_song; + __uint32 trackbytes_per_block=(blocksize_in_bytes / tracks_per_song); + + __uint32 startblocknum=((firstsamnum-(firstsamnum%tracksamples_per_block))/(tracksamples_per_block)); + __uint32 lastsamnum=firstsamnum+samples-1; + __uint32 endblocknum=((lastsamnum-(lastsamnum%tracksamples_per_block))/(tracksamples_per_block)); + for (__uint32 blocknum=startblocknum;blocknum<=endblocknum;blocknum++) + { + // now read trackblocksize_in_sectors sectors from sector blocksec into buffer + //cout << "Reading sec " << blocksector[blocknum] << endl; + + if (blocksector[blocknum]<0x1397f6) { + // safety feature- drop out of write mode when superblock is targeted. + cout << "Detected audio write request to administration area. " << endl; + cout << "Possible bug, dropping out of write mode. " << endl; + setrehearsemode(true); + } + + parentfs->readsectors(parentfs->devhd24, + blocksector[blocknum], + scratchbook, + blocksize_in_sectors); // raw audio read, no fstfix needed + + // now overwrite only the armed tracks with contents of buffer + __uint32 numtracks=0; + if (!(this->isrehearsemode())) { + + for (__uint32 tracknum=1; tracknum<=tracks_per_song; tracknum++) { + if (!(this->trackarmed(tracknum))) { + continue; + } + numtracks++; + //cout << "track "<0) { + //cout << "writing back " << numtracks + // << " tracks to sector "<< blocksector[blocknum] << endl; + parentfs->writesectors(parentfs->devhd24, + blocksector[blocknum], + scratchbook, + blocksize_in_sectors); + } + } + } + return firstsamnum%tracksamples_per_block; +} + +void hd24song::startrecord(int recordmode) +{ + // TODO: recordmode to distinguish between realtime and copy mode + recordmode=recordmode; + this->busyrecording=true; +} + +void hd24song::stoprecord() +{ + this->busyrecording=false; +} + +bool hd24song::recording() +{ + return (this->busyrecording); +} + + +void hd24song::readenabletrack(__uint32 tracknum,bool enable) +{ + if (tracknum<1) return; + if (tracknum>24) return; + if (tracknum>logical_channels()) return; + track_readenabled[tracknum-1]=enable; +} + +void hd24song::readenabletrack(__uint32 tracknum) +{ + readenabletrack(tracknum,true); +} + +bool hd24song::isrehearsemode() +{ + return this->rehearsemode; +} + +void hd24song::setrehearsemode(bool p_rehearsemode) +{ + this->rehearsemode=p_rehearsemode; + return; +} + +void hd24song::trackarmed(__uint32 tracknum,bool arm) +{ + if (tracknum<1) return; + if (tracknum>24) return; + if (tracknum>logical_channels()) return; + track_armed[tracknum-1]=arm; + return; +} + +bool hd24song::trackarmed(__uint32 tracknum) +{ + if (tracknum<1) return false; + if (tracknum>24) return false; + return track_armed[tracknum-1]; +} + +bool hd24song::istrackmonitoringinput(__uint32 tracknum) +{ + // TODO: PROPERLY SET TRANSPORT STATUS! (for now done by GUI) + + if (tracknum<1) return false; + if (tracknum>(this->logical_channels())) return false; + + // indicates if a given track is (supposed to be) + // monitoring input (if false, playback is being monitored). + // This is based on the following decision matrix: + // + // All input | auto input | Track rec-enabled | Transport status | result + // ----------+------------+-------------------+------------------+-------- + // on | | don't care | don't care | true + // off | off | false | stop | false + // off | off | false | play | false + // off | off | false | rec | false + // off | off | true | stop | true + // off | off | true | play | true + // off | off | true | rec | true + // off | on | false | stop | false + // off | on | false | play | false + // off | on | false | rec | false + // off | on | true | stop | true + // off | on | true | play | false + // off | on | true | rec | true + // ----------+------------+-------------------+------------------+-------- + if (parentfs->isallinput()) { + return true; + } + if (!(this->trackarmed(tracknum))) return false; + + if (this->parentfs->transportstatus==hd24fs::TRANSPORTSTATUS_PLAY) { + if (this->parentfs->isautoinput()) { + return false; + } + } + return true; +} + +__uint32 hd24song::getnextfreesector(__uint32 lastallocsector) +{ + /* Based on the alloc info of the current song, this function + will return the sector number of the next unallocated cluster. + When no unallocated sectors are found, the function will return 0. + + Sector 0 is never in the data area, so this will allow us to + distinguish between this situation and real cluster numbers. + Sector 0 is the superblock- as allocation implies writing to the + drive, the code calling this function MUST verify the result. + + When the allocation info cannot be decided upon based on just + the unallocated song sectors within the last allocated cluster + for the song, this function will ask the file system for the + sector number of the next unused cluster. + + */ +#if (SONGDEBUG==1) + cout << "Song::getnextfreesec(" << lastallocsector << ")" << endl; +#endif + // lastallocentrynum=last used allocation entry + __uint32 allocsector=Convert::getint32(buffer,SONGINFO_ALLOCATIONLIST + +(ALLOCINFO_ENTRYLEN*lastallocentrynum)+ALLOCINFO_SECTORNUM); + __uint32 allocblocks=Convert::getint32(buffer,SONGINFO_ALLOCATIONLIST + +(ALLOCINFO_ENTRYLEN*lastallocentrynum)+ALLOCINFO_AUDIOBLOCKSINBLOCK); + __uint32 nextsec=0; + + if ((allocsector==0) && (lastallocsector==0)) + { + // no sectors allocated yet within song. + nextsec=this->parentfs->getnextfreesector(CLUSTER_UNDEFINED); + } else { + // find out first cluster used by allocation unit + __uint32 alloccluster; + __uint32 blockspercluster; + __uint32 clustersused; + __uint32 lastalloccluster; + if (allocsector==0) { + lastalloccluster=parentfs->sector2cluster(lastallocsector); + } else { + alloccluster=parentfs->sector2cluster(allocsector); + blockspercluster=parentfs->getblockspercluster(); + clustersused=allocblocks/blockspercluster; + lastalloccluster=alloccluster+(clustersused-1); + } + + // check if allocation entry fills up the current cluster word + // if not, allocate another cluster within current alloc entry + // otherwise, ask the FS for drive space + // (update song alloc info) + + nextsec=this->parentfs->getnextfreesector(lastalloccluster); + } + + if (nextsec==0) + { + /* + TODO: safety feature: If getnextfreesector returns 0, record + mode will be disabled to prevent accidentally overwriting the + superblock. (Alternatively transport may be stopped but + auto-stop hasn't been fully designed yet). */ + // write protect of some sort + setrehearsemode(true); + } + return nextsec; +} + +void hd24song::save() +{ + __uint32 songsector=parentproject->getsongsectornum(this->mysongid); +#if (SONGDEBUG == 1) + cout << "writing buffer to sector " << songsector << ", " <fstfix(buffer,TOTAL_SECTORS_PER_SONG*512); // sector is now once again in native format + + parentfs->setsectorchecksum(buffer,0,songsector,2); // checksum for 2 sectors of song data + parentfs->setsectorchecksum(buffer,2*512,songsector+2,5); // checksum for 5 sectors of allocation data + + parentfs->writesectors(parentfs->devhd24, + songsector, + buffer,TOTAL_SECTORS_PER_SONG); + + parentfs->fstfix(buffer,TOTAL_SECTORS_PER_SONG*512); // sector is now in 'fixed' format again + if (this->lengthened) + { +#if (SONGDEBUG == 1) + cout << "song was lengthened, update of drive usage needed." << endl; +#endif + parentfs->savedriveusage(); + this->lengthened=false; + } else + { +#if (SONGDEBUG == 1) + cout << "song was not lengthened, no update of drive usage needed." << endl; +#endif + } + parentfs->commit(); +} 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 @@ +#include "hd24transferengine.h" +#include +#include +#include + +#define HD24TRANSFERDEBUG 0 +#define MAXCHANNELS 24 +#define TRACKACTION_UNDEF -1 + +hd24transferjob::hd24transferjob() +{ +#if (HD24TRANSFERDEBUG==1) + cout << "hd24transferjob::hd24transferjob();" << endl; +#endif + init_vars(); +} + +hd24transferjob::~hd24transferjob() +{ +#if (HD24TRANSFERDEBUG==1) + cout << "hd24transferjob::~hd24transferjob();" << endl; +#endif + + if (trackselected!=NULL) + { + delete trackselected; + trackselected=NULL; + } + usecustomrate=0; // by default, match export samrate with song rate + if (m_projectdir!=NULL) + { + delete m_projectdir; + m_projectdir=NULL; + } +} + +void hd24transferjob::init_vars() +{ +#if (HD24TRANSFERDEBUG==1) + cout << "hd24transferjob::init_vars()" << endl; +#endif + this->wantsplit=1; + trackselected=new int[MAXCHANNELS]; + for (int i=0;ifilepath[i]=NULL; + this->filehandle[i]=NULL; + this->m_trackaction[i]=TRACKACTION_UNDEF; // undefined trackaction + } + return; +} + +void hd24transferjob::trackaction(int base1tracknum,int action) +{ +#if (HD24TRANSFERDEBUG==1) + cout << "hd24transferjob::trackaction(base1track=" + << base1tracknum << ", action=" << action << ")" << endl; +#endif + + m_trackaction[base1tracknum-1]=action; +} + +int hd24transferjob::trackaction(int base1tracknum) +{ +#if (HD24TRANSFERDEBUG==1) + cout << "returning hd24transferjob::trackaction(base1track=" + << base1tracknum << ")=" << m_trackaction[base1tracknum-1] + << endl; +#endif + return m_trackaction[base1tracknum-1]; +} + +void hd24transferengine::trackaction(int base1tracknum,int action) +{ + job->trackaction(base1tracknum,action); +} + +int hd24transferengine::trackaction(int base1tracknum) +{ + return job->trackaction(base1tracknum); +} + +char* hd24transferjob::sourcefilename(int base1tracknum) +{ + if (base1tracknum<1) return NULL; + if (base1tracknum>24) return NULL; + return filepath[base1tracknum-1]; +} + +void hd24transferjob::sourcefilename(int base1tracknum,const char* filename) +{ + /* set nth filename to the given char string */ + if (base1tracknum<1) return; + if (base1tracknum>24) return; + + if (filepath[base1tracknum-1]!=NULL) + { + free(filepath[base1tracknum-1]); + } + __uint32 n=strlen(filename); + char* tmpbuf=(char*)malloc(n); + filepath[base1tracknum-1]=tmpbuf; + strncpy(tmpbuf,filename,n+1); + return; +} + +void hd24transferengine::sourcefilename(int base1tracknum,const char* filename) +{ + job->sourcefilename(base1tracknum,filename); +} + +char* hd24transferengine::sourcefilename(int base1tracknum) +{ + return job->sourcefilename(base1tracknum); +} + +void hd24transferjob::startoffset(__uint32 newoff) +{ + m_startoffset=newoff; +} + +void hd24transferjob::endoffset(__uint32 newoff) +{ + m_endoffset=newoff; +} + +__uint32 hd24transferjob::startoffset() +{ + return m_startoffset; +} + +__uint32 hd24transferjob::endoffset() +{ + return m_endoffset; +} + +hd24fs* hd24transferjob::sourcefs() +{ + return this->jobsourcefs; +} + +hd24song* hd24transferjob::sourcesong() +{ + return this->jobsourcesong; +} + +void hd24transferjob::sourcefs(hd24fs* fs) +{ + this->jobsourcefs=fs; +} + +void hd24transferjob::sourcesong(hd24song* song) +{ + this->jobsourcesong=song; + this->jobsourcefs=jobsourcesong->parentfs; +} + +hd24fs* hd24transferjob::targetfs() +{ + return this->jobtargetfs; +} + +hd24song* hd24transferjob::targetsong() +{ + return this->jobtargetsong; +} + +void hd24transferjob::targetfs(hd24fs* fs) +{ + this->jobtargetfs=fs; +} + +void hd24transferjob::targetsong(hd24song* song) +{ + this->jobtargetsong=song; + this->jobtargetfs=jobtargetsong->parentfs; +} + +void hd24transferjob::projectdir(const char* projdir) +{ +#if (HD24TRANSFERDEBUG==1) + cout << "hd24transferjob::projectdir("<c_str(); +} + +void hd24transferengine::lasterror(const char* errormessage) +{ + if (m_lasterror!=NULL) + { + delete m_lasterror; + } + m_lasterror=new string(errormessage); + return; +} + +string* hd24transferengine::lasterror() +{ + return m_lasterror; +} + + +int hd24transferengine::format_outputchannels(int format) +{ + return m_format_outputchannels[format]; +} + +const char* hd24transferengine::projectdir() +{ + cout << "returning hd24transferengine::projectdir()"<projectdir(); +} + +void hd24transferengine::projectdir(const char* projdir) +{ +#if (HD24TRANSFERDEBUG==1) + cout << "hd24transferengine::projectdir("<projectdir(projdir); + return; +} + +hd24transferengine::hd24transferengine() +{ +#if (HD24TRANSFERDEBUG==1) + cout <<"hd24transferengine::hd24transferengine()" << endl; +#endif + init_vars(); +} + +hd24transferengine::~hd24transferengine() +{ +#if (HD24TRANSFERDEBUG==1) + cout <<"hd24transferengine::~hd24transferengine()" << endl; +#endif + if (m_lasterror!=NULL) + { + delete m_lasterror; + m_lasterror=NULL; + } + if (job!=NULL) + { + delete job; + job=NULL; + } +} + +void hd24transferengine::init_vars() +{ + songnum=0; + totsongs=0; + ui=NULL; + totbytestotransfer=0; + totbytestransferred=0; + prefix=0; + transfer_cancel=0; + trackspergroup=0; + transfermixer=NULL; + job=NULL; + m_lasterror=NULL; + job=new hd24transferjob(); + this->uiconfirmfunction=NULL; + this->setstatusfunction=NULL; + soundfile=NULL; +#if (HD24TRANSFERDEBUG==1) + cout << "hd24transferengine::init_vars() - job="<; + m_format_shortdesc=new vector; + populate_formatlist(); +} + +void hd24transferengine::populate_formatlist() +{ +#if (HD24TRANSFERDEBUG==1) + cout << "hd24transferengine::populate_formatlist()" << endl; +#endif +/* Set up transfer format list */ + formatcount=0; + m_format_shortdesc->push_back("WAV (24 bit), mono"); + m_format_outputformat[formatcount]=SF_FORMAT_WAV|SF_FORMAT_PCM_24|SF_ENDIAN_LITTLE; + m_format_outputchannels[formatcount]=1; // mono + m_format_bitdepth[formatcount]=24; + m_format_sndfile[formatcount]=false; // do not use libsndfile for this file format. + m_format_outputextension->push_back(".wav"); + formatcount++; + + m_format_shortdesc->push_back("WAV (24 bit), stereo"); + m_format_outputformat[formatcount]=SF_FORMAT_WAV|SF_FORMAT_PCM_24|SF_ENDIAN_LITTLE; + m_format_outputchannels[formatcount]=2; // stereo + m_format_bitdepth[formatcount]=24; + m_format_sndfile[formatcount]=true; + m_format_outputextension->push_back(".wav"); + formatcount++; + + m_format_shortdesc->push_back("WAV (24 bit), multi"); + m_format_outputformat[formatcount]=SF_FORMAT_WAV|SF_FORMAT_PCM_24|SF_ENDIAN_LITTLE; + m_format_outputchannels[formatcount]=0; // multi + m_format_bitdepth[formatcount]=24; + m_format_sndfile[formatcount]=true; + m_format_outputextension->push_back(".wav"); + formatcount++; + + m_format_shortdesc->push_back("AIF (24 bit), mono"); + m_format_outputformat[formatcount]=SF_FORMAT_AIFF|SF_FORMAT_PCM_24; + m_format_outputchannels[formatcount]=1; // mono + m_format_bitdepth[formatcount]=24; + m_format_sndfile[formatcount]=false; + m_format_outputextension->push_back(".aif"); + formatcount++; + + m_format_shortdesc->push_back("AIF (24 bit), stereo"); + m_format_outputformat[formatcount]=SF_FORMAT_AIFF|SF_FORMAT_PCM_24; + m_format_outputchannels[formatcount]=2; // stereo + m_format_bitdepth[formatcount]=24; + m_format_sndfile[formatcount]=true; + m_format_outputextension->push_back(".aif"); + formatcount++; + + m_format_shortdesc->push_back("AIF (24 bit), multi"); + m_format_outputformat[formatcount]=SF_FORMAT_AIFF|SF_FORMAT_PCM_24; + m_format_outputchannels[formatcount]=0; // stereo + m_format_bitdepth[formatcount]=24; + m_format_sndfile[formatcount]=true; + m_format_outputextension->push_back(".aif"); + formatcount++; + selectedformat(0); +} + +const char* hd24transferengine::getformatdesc(int formatnum) +{ + return ((*m_format_shortdesc)[formatnum]).c_str(); +} + +int hd24transferengine::supportedformatcount() +{ + return formatcount; +} + +void hd24transferengine::trackselected(__uint32 base0tracknum,bool selected) +{ + if (base0tracknum<0) return; + if (base0tracknum>=MAXCHANNELS) return; + + if (selected) + { + job->trackselected[base0tracknum]=1; + } else { + job->trackselected[base0tracknum]=0; + } + return; +} + +bool hd24transferengine::trackselected(__uint32 base0tracknum) +{ + if (base0tracknum<0) return false; + if (base0tracknum>=MAXCHANNELS) return false; + + return ((job->trackselected[base0tracknum])==1); +} + + +void hd24transferengine::openbuffers(unsigned char** audiobuf, + unsigned int channels, + unsigned int bufsize) +{ +#if (HD24TRANSFERDEBUG==1) + cout << "hd24transferengine::openbuffers" << endl; +#endif + + for (unsigned int handle=0;handlesourcefilename(handle+1))==0) { +#if (HD24TRANSFERDEBUG!=0) + cout << "Channel not selected for transfer, skipping" << endl; +#endif + continue; + } + trackcount++; + +#if (HD24TRANSFERDEBUG!=0) + cout << "Channel selected for transfer" << endl; + cout << "That brings the total track count to " + << trackcount << endl; + cout << "job=" << job << endl; + cout << "soundfile=" << soundfile << endl; + cout << "sourcefilename=" << job->sourcefilename(handle+1) + << endl; +#endif + + job->filehandle[handle]=soundfile->sf_open(job->sourcefilename(handle+1),SFM_READ,&sfinfoin[handle]); + if (!(job->filehandle[handle])) + { + cannotopen=1; + continue; + } + } + + return (cannotopen==0); // return true if successful, flase otherwise +} + +bool hd24transferengine::openoutputfiles(hd24sndfile** filehandle,unsigned int channels,unsigned int partnum,int prefix) +{ + trackspergroup=0; + + SF_INFO sfinfoout; + bool uselibsndfile=m_format_sndfile[selectedformat()]; + sfinfoout.format=m_format_outputformat[selectedformat()]; + int chcount=0; + if (m_format_outputchannels[selectedformat()]==0) { + // count channels + for (unsigned int handle=0;handletrackselected[handle]!=0) { + chcount++; + } + } + sfinfoout.channels=chcount; + } else { + sfinfoout.channels=m_format_outputchannels[selectedformat()]; + } + if (job->usecustomrate==1) { + long samrate=job->stamprate; + sfinfoout.samplerate=samrate; + } else { + sfinfoout.samplerate=job->sourcesong()->samplerate(); + } + // chcount and lasthandle are intended to allow + // support for writing multichannel files. + int lasthandle=0; + int lasttrack=-1; + int trackcount=0; + int cannotopen=0; + chcount=0; + for (unsigned int handle=0;handletrackselected[handle]==0) { + // channel not selected for export + continue; + } + trackcount++; + lasttrack=handle; + + string* fname=generate_filename(handle,partnum,prefix); + if (fname==NULL) + { + /* cannot generate filename. Most likely cause is + no song set */ + return false; // problem opening files. + } + if (chcount==0) { + isfirstchanofgroup[handle]=true; + if (uselibsndfile) + { + filehandle[handle]->sndfilehandle=NULL; + if (soundfile->sf_open) { + filehandle[handle]->open(fname->c_str(),(int)SFM_WRITE,&sfinfoout,soundfile); + } + if (!(filehandle[handle]->handle())) + { + cannotopen=1; + } + } + else + { + filehandle[handle]->open(fname->c_str(),(int)SFM_WRITE,&sfinfoout); + } + lasthandle=handle; + } else { + // copy handle of previously opened file to current track + filehandle[handle]->handle(filehandle[lasthandle]->handle(),filehandle[lasthandle]->handletype()); + if (!(filehandle[handle]->handle())) + { + cannotopen=1; + } + } + chcount++; + if ((sfinfoout.channels)!=0) + { + // sfinfoout.channels=0 means full multitrack file + // so only a single file will be opened. + chcount=chcount%(sfinfoout.channels); + if (chcount==0) { + islastchanofgroup[handle]=true; + if (trackspergroup==0) { + trackspergroup=trackcount; + } + } + } + + delete fname; + } + if (lasttrack>=0) + { + if (trackspergroup==0) { + trackspergroup=trackcount; + } + + islastchanofgroup[lasttrack]=true; + } + return (cannotopen==0); // return true if successful, false otherwise +} + +void hd24transferengine::closeinputfiles(SNDFILE** filehandle,unsigned int channels) +{ + SNDFILE* lasthandle=NULL; + for (unsigned int handle=0;handletrackselected[handle]==0) continue; + if (filehandle[handle]!=lasthandle) { + soundfile->sf_close(filehandle[handle]); + lasthandle=filehandle[handle]; + filehandle[handle]=NULL; + } + } +} + +void hd24transferengine::closeoutputfiles(hd24sndfile** filehandle,unsigned int channels) +{ + void* lasthandle=NULL; + + for (unsigned int handle=0;handletrackselected[handle]==0) continue; + if (filehandle[handle]->handle()!=lasthandle) { + lasthandle=(void*)filehandle[handle]->handle(); + if (lasthandle!=NULL) { + filehandle[handle]->close(); + } + } + } +} + +bool hd24transferengine::confirmfileoverwrite() +{ + if (this->uiconfirmfunction==NULL) + { + lasterror("Output files already exist, transfer aborted."); + return false; + } + + return uiconfirmfunction(ui,"One or more output files already exist. " + "Do you want to overwrite them?"); +} + +bool hd24transferengine::overwritegivesproblems(hd24song* thesong,int partnum) +{ + /* this function will return TRUE if overwriting + existing files causes a problem, FALSE otherwise. + + Overwriting files does NOT cause problems if + - no files are going to be overwritten + or + - Files are going to be overwritten but the user + permits us to do so. + + */ + + if (anyfilesexist(thesong)) + { + return (!(confirmfileoverwrite())); + } + return false; +} + +bool hd24transferengine::dontopenoutputfiles(hd24sndfile** filehandle,unsigned int channels,unsigned int partnum,int prefix) +{ + // HACK + trackspergroup=0; + + SF_INFO sfinfoout; + //bool uselibsndfile=m_format_sndfile[selectedformat()]; + sfinfoout.format=m_format_outputformat[selectedformat()]; + int chcount=0; + if (m_format_outputchannels[selectedformat()]==0) { + // count channels + for (unsigned int handle=0;handletrackselected[handle]!=0) { + chcount++; + } + } + sfinfoout.channels=chcount; + } else { + sfinfoout.channels=m_format_outputchannels[selectedformat()]; + } + if (job->usecustomrate==1) { + long samrate=job->stamprate; + sfinfoout.samplerate=samrate; + } else { + sfinfoout.samplerate=job->sourcesong()->samplerate(); + } + // chcount and lasthandle are intended to allow + // support for writing multichannel files. + int lasthandle=0; + int lasttrack=-1; + int trackcount=0; + int cannotopen=0; + chcount=0; + for (unsigned int handle=0;handletrackselected[handle]==0) { + // channel not selected for export + continue; + } + trackcount++; + lasttrack=handle; + + string* fname=generate_filename(handle,partnum,prefix); + if (fname==NULL) + { + // Cannot generate filename. No song set? + return false; // problem (not) opening files. + } + if (chcount==0) { + isfirstchanofgroup[handle]=true; + // if (uselibsndfile) + // { + // filehandle[handle]->sndfilehandle=NULL; + // if (soundfile->sf_open) { + // filehandle[handle]->open(fname->c_str(),(int)SFM_WRITE,&sfinfoout,soundfile); + // } + // if (!(filehandle[handle]->handle())) + // { + // cannotopen=1; + // } + // } + // else + // { + // filehandle[handle]->open(fname->c_str(),(int)SFM_WRITE,&sfinfoout); + // } + lasthandle=handle; + } else { + // copy handle of previously opened file to current track + // filehandle[handle]->handle(filehandle[lasthandle]->handle(),filehandle[lasthandle]->handletype()); + // if (!(filehandle[handle]->handle())) + // { + // cannotopen=1; + // } + } + chcount++; + // if ((sfinfoout.channels)!=0) + // { + // // sfinfoout.channels=0 means full multitrack file + // // so only a single file will be opened. + // chcount=chcount%(sfinfoout.channels); + // if (chcount==0) { + // islastchanofgroup[handle]=true; + // if (trackspergroup==0) { + // trackspergroup=trackcount; + // } + // } + // } + + delete fname; + } + + if (lasttrack>=0) + { + if (trackspergroup==0) { + trackspergroup=trackcount; + } + + islastchanofgroup[lasttrack]=true; + } + return (cannotopen==0); // return true if successful, false otherwise +} +void hd24transferengine::flushbuffer(hd24sndfile** filehandle,unsigned char** buffer,__uint32 flushbytes,unsigned int channels) +{ + #if (HD24TRANSFERDEBUG==1) + cout << "Flushbuffer " << flushbytes << " bytes" <trackselected[handle]==0) continue; + + writerawbuf(&(*filehandle)[handle],buffer[handle],flushbytes); + } + #if (HD24TRANSFERDEBUG==1) + cout << "Flushed" << endl; + #endif +} + +void hd24transferengine::prepare_transfer_to_pc(__uint32 songnum, + __uint32 totsongs,__sint64 totbytestotransfer, + __sint64 totbytestransferred, + int wantsplit,__uint32 prefix) +{ + // set properties as needed + cout << "prepare transfer to pc:" << endl; + cout << "song "<< songnum<< "/" << totsongs << ", "; + cout << totbytestotransfer << " total bytes to transfer" << endl; + cout << totbytestransferred << " transferred so far" << endl; + cout << "wantsplit=" << wantsplit ; + cout << ", prefix=" << prefix << endl; + this->totbytestotransfer=totbytestotransfer; + // this->transfer_to_pc(); +} + +void hd24transferengine::transfer_in_progress(bool active) +{ + // TODO: callback function + // stop_transfer->show(); +} + +void hd24transferengine::mixleft(bool select) +{ + if (select) { job->mixleft=1; } +} + +bool hd24transferengine::mixleft() +{ + if (job->mixleft==1) + { + return true; + } + return false; +} + +void hd24transferengine::mixright(bool select) +{ + if (select) { job->mixright=1; } +} + +bool hd24transferengine::mixright() +{ + if (job->mixright==1) + { + return true; + } + return false; +} + + +__sint64 hd24transferengine::transfer_to_pc() +{ + // function returns bytes transferred for the transfer of only the current file. + + __sint64 totsamcount; /* Total number of samples exported */ + __sint64 partsamcount; /* When splitting up the song into multiple parts, + number of samples exported to current part */ + __sint64 blockcount; /* Allows us to keep a write buffer as cache for + better export performance */ + if (job->sourcesong()==NULL) + { + return 0; + } + if (transfer_cancel==1) + { + return 0; + } + + // limit which tracks need to be actually read from HD24 disk + for (__uint32 i=1;i<=MAXCHANNELS;i++) + { + if (job->trackselected[i-1]==1) + { + job->sourcesong()->readenabletrack(i,true); + } else { + job->sourcesong()->readenabletrack(i,false); + } + } + bool mustmixdown=false; + if (job->mixleft==1) + { + mustmixdown=true; + } + if (job->mixright==1) + { + mustmixdown=true; + } + if (transfermixer==NULL) + { + /* as much as we'd like, there is no mixer so we can't mix. */ + mustmixdown=false; + } + + #if (HD24TRANSFERDEBUG==1) + cout << "start export 1" << endl; + #endif + __uint32 lastremain=0xffffffff; //a + __uint64 songlen_sam=job->sourcesong()->songlength_in_samples()*(job->sourcesong()->physical_channels()/job->sourcesong()->logical_channels()); + __uint32 channels=job->sourcesong()->logical_channels(); + __uint32 bytespersam=(job->sourcesong()->bitdepth()/8); + int mustdeinterlace=0; + if ((job->sourcesong()->samplerate())>=88200) + { + mustdeinterlace=1; + } + __uint32 oldmixersamplerate=0; + if (mustmixdown) + { + if (transfermixer!=NULL) { + oldmixersamplerate=transfermixer->samplerate(); + transfermixer->samplerate(job->sourcesong()->samplerate()); + } + } + + #if (HD24TRANSFERDEBUG==1) + cout << "Channels="<sizelimit(); + + /* + if total number of samples is likely to overflow + max allowable length, ask if user wants to split up + the files. + */ + if (job->wantsplit==1) { + partnum=1; // count part numbers in filename + } else { + partnum=0; // do not count part numbers in filename + MAXBYTES=songlen_sam*bytespersam; // allow the full song length in a single file + } + + /* Start location 0 is absolute, all other offsets + are relative to the start offset. The only difference + is in the timecode. + Because of this, if startoffset>0 is given, we + can ignore this. */ + __uint64 translen; + __uint64 tottranslen=0; // for percentage calc in multi-song exports + signed int stepsize; + if (job->startoffset()>job->endoffset()) + { + __uint32 tempoffset=job->startoffset(); + job->startoffset(job->endoffset()); + job->endoffset(tempoffset); + } + + translen=(job->endoffset()-job->startoffset())*(job->sourcesong()->physical_channels()/job->sourcesong()->logical_channels()); + #if (HD24TRANSFERDEBUG==1) + cout << "startoffset=" << job->startoffset() << endl; + cout << "endoffset=" << job->endoffset() << endl; + #endif + + if (translen==0) + { + lasterror("Start offset equals end offset- nothing to do!"); + } + stepsize=1; + + bool canopen=true; + MixerChannelControl* mixerchannel[24]; + for (unsigned int tracknum=0;tracknumparentui()->mixerchannel[tracknum]->control; + } + // HACK + canopen=dontopenoutputfiles( + (hd24sndfile**)&filehandle[0], + channels, + partnum, + prefix); // partnum is for splitting large files + } else { + canopen=openoutputfiles( + (hd24sndfile**)&filehandle[0], + channels, + partnum, + prefix); // partnum is for splitting large files + } + + if (!canopen) + { + #if (HD24TRANSFERDEBUG==1) + cout << "error opening output files" << endl; + #endif + transfer_cancel=1; + return 0; + } else { + transfer_cancel=0; + } + + this->transfer_in_progress(true); + time (&starttime); + + partsamcount=0; totsamcount=0; + int trackwithingroup=0; + #if (HD24TRANSFERDEBUG==1) + cout << "songlen in samples=" << songlen_sam << endl; + #endif + blockcount=0; // for buffered writing. + hd24fs* currenthd24=job->sourcefs(); + if (currenthd24==NULL) + { + cout << "Critical error- current FS not defined." << endl; + } + int blocksize=currenthd24->getbytesperaudioblock(); + // to hold normally read audio data: + unsigned char* audiodata=(unsigned char*)memutils::mymalloc("ftransfer_to_pc",blocksize,1); + + // for high-samplerate block deinterlacing: + unsigned char* deinterlacedata=(unsigned char*)memutils::mymalloc("ftransfer_to_pc",blocksize,1); + + // for interlacing multi-track data: + unsigned char* interlacedata=(unsigned char*)memutils::mymalloc("ftransfer_to_pc",blocksize,1); + + + __uint32 samplesperblock=(blocksize/channels)/bytespersam; + float* outputBuffer=NULL; + SF_INFO infoblock; + hd24sndfile* mixdownfile=NULL; + if (mustmixdown) + { + outputBuffer=(float*)malloc(2*samplesperblock*sizeof(float)); // 2 because it is stereo + mixdownfile=new hd24sndfile(SF_FORMAT_WAV|SF_FORMAT_PCM_32 + |SF_FORMAT_FLOAT,soundfile); + infoblock.channels=2; + infoblock.samplerate=job->sourcesong()->samplerate(); + infoblock.format=SF_FORMAT_WAV|SF_FORMAT_PCM_32|SF_FORMAT_FLOAT; + + int mixdownfilenum=0; + int fileopensuccess=0; + do { + string* mixdownfilename=new string(""); + *mixdownfilename+=*job->m_projectdir; + string* currsongname=job->sourcesong()->songname(); + *mixdownfilename+=*currsongname; + delete currsongname; + *mixdownfilename+="_mixdown"; + if (mixdownfilenum>0) + { + *mixdownfilename+="_"; + string* mixnumstr=Convert::int2str(mixdownfilenum); + *mixdownfilename+=*mixnumstr; + delete mixnumstr; + } + *mixdownfilename+=".wav"; + if (!hd24utils::fileExists(mixdownfilename->c_str())) + { + mixdownfile->open(mixdownfilename->c_str(),SFM_WRITE,&infoblock,soundfile); + fileopensuccess=1; + } + mixdownfilenum++; + delete mixdownfilename; + } while (fileopensuccess==0); + } + + + __uint32 samplesinfirstblock=samplesperblock; + if (job->startoffset()!=0) { + if (job->startoffset()>=samplesperblock) { + samplesinfirstblock=samplesperblock-(job->startoffset()%samplesperblock); + } else { + samplesinfirstblock=samplesperblock-(job->startoffset()); + } + } + #if (HD24TRANSFERDEBUG==1) + cout << "go to startoffset " << job->startoffset() << endl; + #endif + job->sourcesong()->golocatepos(job->startoffset()); + #if (HD24TRANSFERDEBUG==1) + cout << "got to startoffset " << job->startoffset() << endl; + cout << "translen= " << translen << endl; + #endif + __uint32 subblocksize=samplesperblock*bytespersam; + __uint32 samplesinblock=samplesinfirstblock; + if (translen=translen) + { + subblockbytes=((translen-samplesinfirstblock) % samplesperblock ) *bytespersam; + } else { + if (samplesinblock!=samplesperblock) + { + subblockbytes=samplesinblock*bytespersam; + } + } + } + + #if (HD24TRANSFERDEBUG==1) + cout << "samplenum=" << samplenum << ", sams in block=" << samplesinblock << endl; + #endif + + int skipsams=job->sourcesong()->getmtrackaudiodata(samplenum+job->startoffset(),samplesinblock,&audiodata[0],hd24song::READMODE_COPY); + unsigned char* whattowrite=&audiodata[0]; + if (mustdeinterlace==1) + { + job->sourcesong()->deinterlaceblock(&audiodata[0],&deinterlacedata[0]); + whattowrite=&deinterlacedata[0]; + } + + #if (HD24TRANSFERDEBUG==1) + cout << "check for split" << endl; + #endif + if (job->wantsplit==1) + { + __uint64 filesize=partsamcount; + filesize+=samplesinblock; + filesize*=bytespersam; + if (filesize>MAXBYTES) /// total filesize reached for current part + { + closeoutputfiles((hd24sndfile**)&filehandle[0],channels); + partnum++; + openoutputfiles((hd24sndfile**)&filehandle[0],channels,partnum,prefix); // partnum is for splitting large files + partsamcount=0; + } + } + + // check if we need to save a mixdown + if (mustmixdown) + { +#if (HD24TRANSFERDEBUG==1) + cout << "Mixing " << endl; +#endif + + for (__uint32 tracknum=0;tracknum=(1<<23)) { + subsamval-=(1<<24); + } + subsamval=(subsamval/(double)0x800000); + mixerchannel[tracknum]->sample(samnum/3,subsamval); + } + } + transfermixer->mix(subblockbytes/3); + + if (outputBuffer!=NULL) + { + // if stereo output, interlace (TODO: check if this is what we want) + for (__uint32 i=0;i<(subblockbytes/3);i++) + { + ((float*)outputBuffer)[i*2] = transfermixer->masterout(0,i); // left + ((float*)outputBuffer)[i*2+1] = transfermixer->masterout(1,i); // right + } + mixdownfile->write_float(outputBuffer,(subblockbytes/3)*infoblock.channels); + } + } + // when mixing down, let's not export raw files as well. + + for (__uint32 tracknum=0;tracknumtrackselected[tracknum]==0) + { + // track not selected for export +#if (HD24TRANSFERDEBUG==1) + cout << "Track " << tracknum+1 << " not selected for export " << endl; +#endif + continue; + } + + if (transfer_cancel==1) + { +#if (HD24TRANSFERDEBUG==1) + cout << "Transfer cancelled by user. " << endl; +#endif + break; + } + + // Mono files or multiple tracks? + if ( + (isfirstchanofgroup[tracknum]) + &&(islastchanofgroup[tracknum]) + ) { + // file is mono + if (!mustmixdown) { + writerawbuf(filehandle[tracknum],&whattowrite[tracknum*subblocksize+((mustdeinterlace+1)*skipsams*bytespersam)],subblockbytes); + } + bytestransferred+=subblockbytes; + } else { + if (isfirstchanofgroup[tracknum]) { + // first channel of group, clear interlace buffer + trackwithingroup=0; +#if (HD24TRANSFERDEBUG==1) + cout << "first track " << samplenum << endl; +#endif + } else { + trackwithingroup++; + #if (HD24TRANSFERDEBUG==1) + cout << "nonfirst track " << samplenum << endl; + #endif + } + // interlace channel onto multi channel file buffer + if (!mustmixdown) { + hd24utils::interlacetobuffer(&whattowrite[tracknum*subblocksize+((mustdeinterlace+1)*skipsams*bytespersam)],&interlacedata[0],subblockbytes,bytespersam,trackwithingroup,trackspergroup); + } + + if (islastchanofgroup[tracknum]) { + // last channel of group, write interlace buffer to file + #if (HD24TRANSFERDEBUG==1) + cout << "write track " << samplenum << endl; + #endif + //soundfile->sf_write_raw(filehandle[tracknum],&interlacedata[0],subblockbytes*trackspergroup); + if (!mustmixdown) { + writerawbuf(filehandle[tracknum],&interlacedata[0],subblockbytes*trackspergroup); + } + bytestransferred+=subblockbytes*trackspergroup; + } + } + } + partsamcount+=(subblockbytes/bytespersam); + // totsamcount+=subblockbytes; + + __uint32 pct; // to use for display percentage + double dblpct; // to use for ETA calculation + #if (HD24TRANSFERDEBUG==1) + cout << "about to calc pct" << endl; + cout << "totbytestransferred=" << totbytestransferred; + cout << ", currbytestransferred=" << bytestransferred; + cout << ", totbytestotransfer=" << totbytestotransfer; + cout << endl; + #endif + + /* following two calculations give the same mathematical result + but help keep the required word length narrow for large numbers + and reduce floating point rounding errors for small numbers. + */ + if (tottranslen<100000) + { + dblpct=( + ( + ( + (double)totbytestransferred + +(double)bytestransferred + ) + *(double)100 + ) + / + (double)totbytestotransfer + ); + } + else + { + dblpct=( + ( + (double)totbytestransferred + +(double)bytestransferred + ) + / + (double) + ( + (double)totbytestotransfer + / + (double)100 + ) + ); + } + pct=(__uint32)(dblpct); + + #if (HD24TRANSFERDEBUG==1) + cout << "about to calc pct2" << endl; + #endif + + #if (HD24TRANSFERDEBUG==1) + cout << "computed pct " << samplenum << endl; + #endif + time (&endtime); + olddifseconds=difseconds; + difseconds=(long long int)difftime(endtime,starttime); + + if (((dblpct-oldpct)>=1) || ((difseconds-olddifseconds)>=1)) + { + /* update on percentage change, and also every + so many samples (to allow frequent enough + screen updates with large audio files) */ + oldpct=dblpct; + + string pctmsg="Transferring audio to PC... "; + if (totsongs>1) + { + pctmsg+="Song "; + string* cursongnum=Convert::int2str(songnum); + pctmsg+=*cursongnum+"/"; + delete cursongnum; + string* totsongnum=Convert::int2str(totsongs); + pctmsg+=*totsongnum+", "; + delete totsongnum; + } + string* strpct=Convert::int2str(pct); + pctmsg+=*strpct+"%"; + + if (pct>0) + { + __uint32 estimated_seconds=(__uint32)((difseconds*100)/dblpct); + __uint32 remaining_seconds=estimated_seconds-difseconds; + + lastremain=remaining_seconds; + + __uint32 seconds=(lastremain%60); + __uint32 minutes=(lastremain-seconds)/60; + __uint32 hours=0; + + pctmsg+=" Time remaining: "; + + if (minutes>59) { + hours=(minutes/60); + minutes=(minutes%60); + string* strhours=Convert::int2str(hours,2,"0"); + pctmsg+=*strhours; + pctmsg+=":"; + delete(strhours); + } + + string* minsec=Convert::int2str(minutes,2,"0"); + + *minsec+=":"; + + string* strsecs=Convert::int2str(seconds,2,"0"); + *minsec+=*strsecs; + delete(strsecs); + + pctmsg+=*minsec; + delete(minsec); + } + + delete (strpct); + setstatus(ui,&pctmsg,dblpct); + } + } + + closeoutputfiles((hd24sndfile**)&filehandle[0],channels); + for (int i=0;itrackselected[i-1]==1) + { + job->sourcesong()->readenabletrack(i,true); + } + } + if (audiodata!=NULL) + { + free (audiodata); + } + if (deinterlacedata!=NULL) + { + free (deinterlacedata); + } + if (interlacedata!=NULL) + { + free (interlacedata); + } + if (outputBuffer!=NULL) + { + free (outputBuffer); + } + if (mixdownfile!=NULL) + { + mixdownfile->close(); + } + if (transfermixer!=NULL) { + transfermixer->samplerate(oldmixersamplerate); + } + + return bytestransferred; +} + +void hd24transferengine::selectedformat(int i) +{ + if (i>=formatcount) return; + job->selectedformat(i); +} +void hd24transferjob::selectedformat(int i) +{ + m_selectedformat=i; +} + +int hd24transferengine::selectedformat() +{ + return job->selectedformat(); +} +int hd24transferjob::selectedformat() +{ + return m_selectedformat; +} + +void hd24transferengine::mixer(MixerControl* m_mixer) +{ + this->transfermixer=m_mixer; +} + +MixerControl* hd24transferengine::mixer() +{ + return this->transfermixer; +} + +string* hd24transferengine::generate_filename(int tracknum,int partnum,int prefix) +{ +#if (HD24TRANSFERDEBUG==1) + cout << "hd24transferengine::generate_filename(track=" << tracknum << ",part="<m_projectdir->c_str(); //projectdir(); +#if (HD24TRANSFERDEBUG==1) + cout << "Projdir (const char*)="<substr(dirname->length()-1,1)!="/") { + *dirname+="/"; + } +#if (HD24TRANSFERDEBUG==1) + cout << "filename so far is just dir with slash=" << *dirname << endl; +#endif + string* fname=new string(dirname->c_str()); + delete dirname; + if (prefix!=0) + { + string* strsongnum=Convert::int2str(prefix,2,"0"); + *fname+="Song"; + *fname+=*strsongnum; + *fname+="-"; + delete (strsongnum); + } +#if (HD24TRANSFERDEBUG==1) + cout << "filename so far is " << *fname << endl; + cout << "About to add songname" << endl; +#endif + if (job->sourcesong()==NULL) + { +#if (HD24TRANSFERDEBUG==1) + cout << "No song set!" << endl; +#endif + return NULL; + } + + string* strsongname=job->sourcesong()->songname(); + *fname+=*strsongname; + delete (strsongname); + +#if (HD24TRANSFERDEBUG==1) + cout << "filename so far is " << *fname << endl; + cout << "About to add track constant" << endl; +#endif + *fname+="-Track"; +#if (HD24TRANSFERDEBUG==1) + cout << "filename so far is " << *fname << endl; + cout << "About to add tracknum" << (tracknum+2) << endl; +#endif + string* strtracknum=Convert::int2str(tracknum+1,2,"0"); + *fname+=*strtracknum; + delete (strtracknum); + if (partnum>0) { + /* partnum 0 implies no splitting and thus no partnum + added to the filename. In other words, we either use + partnum 0 (invisible in filename), or partnum 1-n. */ + *fname+="_part"; + *fname+=*Convert::int2str(partnum); + } + string* extension=new string((*m_format_outputextension)[selectedformat()]); + *fname+=*extension; + delete extension; +#if (HD24TRANSFERDEBUG==1) + cout << "Generated filename="<llsizelimit=p_sizelimit; +} + +__sint64 hd24transferjob::sizelimit() +{ + return this->llsizelimit; +} + +void hd24transferengine::sizelimit(__sint64 p_sizelimit) +{ + job->sizelimit(p_sizelimit); +} + +__sint64 hd24transferengine::sizelimit() +{ + return job->sizelimit(); +} + +bool hd24transferengine::anyfilesexist(hd24song* thesong) +{ + bool anyexist=false; + struct stat fi; + __uint32 channels=thesong->logical_channels(); + for (unsigned int q=0; q<100; q++) + { + for (unsigned int handle=0;handletrackselected[handle]==0) + { + // channel not selected for export + continue; + } + string* fname=this->generate_filename(handle,0,q); + if (fname==NULL) + { + // cannot generate filename (no song set?) + break; + } +#if (HD24TRANSFERDEBUG==1) + cout << "check if file exists:" << *fname << endl; +#endif + if ((stat (fname->c_str(), &fi) != -1) && ((fi.st_mode & S_IFDIR) == 0)) + { + anyexist=true; +#if (HD24TRANSFERDEBUG==1) + cout << "yes, exists" << *fname << endl; +#endif + delete fname; + break; + } + + fname=this->generate_filename(handle,1,q); + if (fname==NULL) + { + // cannot generate filename (no song set?) + break; + } +#if (HD24TRANSFERDEBUG==1) + cout << "check if file exists:" << *fname << endl; +#endif + if ((stat (fname->c_str(), &fi) != -1) && ((fi.st_mode & S_IFDIR) == 0)) + { + anyexist=true; +#if (HD24TRANSFERDEBUG==1) + cout << "yes, exists" << *fname << endl; +#endif + delete fname; + break; + } +#if (HD24TRANSFERDEBUG==1) + cout << "no, doesnt exist" << endl; +#endif + + delete fname; + } + if (anyexist==true) break; + } + return anyexist; +} + +void hd24transferengine::setstatus(void* ui,string* message,double percentage) +{ +#if (HD24TRANSFERDEBUG==1) + printf(message->c_str(),percentage); + cout << endl; +#endif + if (setstatusfunction!=NULL) + { + setstatusfunction(ui,message->c_str(),percentage); + } + return; +} + +void hd24transferengine::set_ui(void* p_ui) +{ + this->ui=p_ui; +} + +void hd24transferengine::sourcesong(hd24song* song) +{ +#if (HD24TRANSFERDEBUG==1) + cout << "hd24transferengine::sourcesong(" << song << ")" << endl; +#endif + if (this->job==NULL) + { + return; + } + this->job->sourcesong(song); +} + +hd24song* hd24transferengine::sourcesong() +{ +#if (HD24TRANSFERDEBUG==1) + cout << "hd24transferengine::sourcesong()=" + << this->job->sourcesong()<< endl; +#endif + if (this->job==NULL) + { + return NULL; + } + return this->job->sourcesong(); +} + +void hd24transferengine::startoffset(__uint32 newoff) +{ + job->startoffset(newoff); +} + +void hd24transferengine::endoffset(__uint32 newoff) +{ + job->endoffset(newoff); +} + +__uint32 hd24transferengine::startoffset() +{ + return job->startoffset(); +} + +__uint32 hd24transferengine::endoffset() +{ + return job->endoffset(); +} + +void hd24transferengine::targetsong(hd24song* song) +{ + if (job==NULL) + { + return; + } + job->targetsong(song); +} + +hd24song* hd24transferengine::targetsong() +{ + if (job==NULL) + { + return NULL; + } + return job->targetsong(); +} + +__sint64 hd24transferengine::transfer_to_hd24() +{ + if (job->targetsong()==NULL) + { + lasterror("No target song selected, transfer aborted."); + return 0; + } + if (soundfile==NULL) + { + lasterror("soundfile library not defined, transfer aborted"); + return 0; + } + job->targetsong()->golocatepos(0); + job->targetsong()->startrecord(hd24song::WRITEMODE_COPY); + + //mustdisplaytimer=false; + __sint64 bytestransferred=0; + + for (unsigned int currchan=0;currchanfilehandle[currchan]=NULL; + audiobuf[currchan]=NULL; + } + SF_INFO sfinfoin[24]; + bool canopen=this->openinputfiles((SNDFILE**)&(job->filehandle[0]),(SF_INFO*)&sfinfoin[0],job->targetsong()->logical_channels()); + if (!canopen) + { + return 0; + } + // Find file with largest number of samples; + // if song is shorter than that, lengthen song to fit it. + __sint64 translen=job->targetsong()->songlength_in_samples(); + __uint32 maxlen=(__uint32)translen; + bool mustlengthensong=false; + for (int i=0;ifilehandle[i]==NULL) continue; + if (((__sint64)sfinfoin[i].frames) > (__sint64)maxlen) { + maxlen=sfinfoin[i].frames; + mustlengthensong=true; + } + } + if (mustlengthensong) { + string* lengthening=new string("Transferring audio to HD24... "); + setstatus(ui,lengthening,0); + delete lengthening; + #if (HD24TRANSFERDEBUG==1) + cout << "about to start lengthening song to maxlen=" << maxlen << endl; + #endif + bool clearnew=false; // do not silence newly allocated part + // (it is done automatically during transfer) + translen=job->targetsong()->songlength_in_samples(maxlen,clearnew); + #if (HD24TRANSFERDEBUG==1) + cout << "verifying actual song length " << endl; + cout << "new len=" << translen << endl; + #endif + if (translen!=maxlen) + { + #if (HD24TRANSFERDEBUG==1) + cout << "new len<> maxlen so not enough space." << endl; + #endif + this->lasterror("Not enough space on HD24 drive."); + return 0; + } + job->targetsong()->save(); + // ui_refresh("tohd24"); + #if (HD24TRANSFERDEBUG==1) + cout << "translen is now " << translen << endl; + #endif + + } + hd24fs* currenthd24=job->targetfs(); + int blocksize=currenthd24->getbytesperaudioblock(); + // to hold normally read audio data: + unsigned char* audiodata=NULL; + transfer_cancel=0; +// ui->stop_transfer->show(); + + audiodata=(unsigned char*)memutils::mymalloc("button_transfertohd24",blocksize,1); + __uint32 channels=job->targetsong()->logical_channels(); + __uint32 bytespersam=(job->targetsong()->bitdepth()/8); + __uint32 samplesperblock=(blocksize/channels)/bytespersam; + job->smptegen=new SMPTEgenerator(job->targetsong()->samplerate()); + + for (unsigned int fh=0;fhtrackaction(fh+1); + if ((job->filehandle[fh]!=NULL)||(action<=1 /* erase, SMPTE stripe */)) { + __uint32 chans=((action==0)||(action==1))?(1):(sfinfoin[fh].channels); + __uint32 bytestoalloc=chans*samplesperblock*sizeof(int); + audiobuf[fh]=(int*)memutils::mymalloc( + "button_transfertohd24 audiobuf",bytestoalloc,1 + ); + + if (action == 0) { + // clear erase buffer once + int* buf=audiobuf[fh]; + for (__uint32 samnum=0;samnumtargetsong()->samplerate())>=88200) + { + mustinterlace=1; + } + #if (HD24TRANSFERDEBUG==1) + cout << "Channels="<songlength_in_samples(); + __uint32 samplesinfirstblock=samplesperblock; + + job->targetsong()->getlocatepos(25); // 25= virtual endpoint of song + // calc number of samples to transfer. + // for high samplerate songs, this is twice the songlength. + // (for partial transfers, which are not supported at this time, the + // number of samples is based on (endoffset-startoffset) instead of songlength + translen=job->targetsong()->songlength_in_samples()*(job->targetsong()->physical_channels()/job->targetsong()->logical_channels()); + __uint64 totbytestotransfer=translen*bytespersam; + //transfer_to_hd24(); + + if (startoffset!=0) { + if (startoffset>=samplesperblock) { + samplesinfirstblock=samplesperblock-(startoffset%samplesperblock); + } else { + samplesinfirstblock=samplesperblock-startoffset; + } + } + #if (HD24TRANSFERDEBUG==1) + cout << "go to startoffset " << startoffset << endl; + #endif + job->targetsong()->golocatepos(startoffset); + #if (HD24TRANSFERDEBUG==1) + cout << "got to startoffset " << startoffset << endl; + cout << "translen= " << translen << endl; + #endif + + __uint32 samplesinblock=samplesinfirstblock; + if (translen=translen) + { + subblockbytes=((translen-samplesinfirstblock) % samplesperblock ) *bytespersam; + } else { + if (samplesinblock!=samplesperblock) + { + subblockbytes=samplesinblock*bytespersam; + } + } + } + + #if (HD24TRANSFERDEBUG==1) + cout << "samplenum=" << samplenum << ", sams in block=" << samplesinblock << endl; + #endif + + /* + // disable multipart files for now (this function transfers TO HD24 drives) + if (wantsplit==1) + { + if (((partsamcount+samplesinblock)*bytespersam)>MAXBYTES) /// total filesize reached for current part + { + this->closeoutputfiles((SNDFILE**)&filehandle[0],channels); + partnum++; + this->openoutputfiles((SNDFILE**)&filehandle[0],channels,partnum,prefix); // partnum is for splitting large files + partsamcount=0; + } + } + */ + for (__uint32 tracknum=0;tracknumtargetsong()->trackarmed(tracknum+1))) + { + // track not selected for export + continue; + } + __uint32 samsread=0; + int action=job->trackaction(tracknum+1); + unsigned int trackchans=1; + + if (action==0) { /* 0=ERASE */ + #if (HD24TRANSFERDEBUG==1) + cout << "track " << tracknum+1 << " marked for erase" << endl; + + #endif + samsread=samplesinblock; + } else { + if (action==1) + { + #if (HD24TRANSFERDEBUG==1) + cout << "track " << tracknum+1 << " marked for stripe" << endl; + + #endif + /* Stripe track with SMPTE/LTC here */ + + int* buf=audiobuf[tracknum]; + + for (__uint32 samnum=0;samnumsmptegen->getbit(samplenum+samnum)*2)-1)*2000000; + } + /* End of stripe */ + samsread=samplesinblock; + } else { + trackchans=sfinfoin[tracknum].channels; + if (job->filehandle[tracknum] == NULL) { + continue; + } + samsread=soundfile->sf_read_int( + job->filehandle[tracknum], + audiobuf[tracknum], + samplesinblock*trackchans); + #if (HD24TRANSFERDEBUG==1) + cout << "sams read=" + << samsread + << endl; + #endif + } + } + // we replace the deinterlaced data with file audio + //sf_write_raw(filehandle[tracknum],&whattowrite[tracknum*subblocksize+((mustdeinterlace+1)*skipsams*bytespersam)],subblockbytes); + + + + // cout << "replace audio block on track " << tracknum+1 << endl; + + //filehandle[tracknum]; + + // libsndfile converts all files to 32-bit samples, but we only use 24 bit, + // so we divide by 256 to shift out the unused 8 bits. + + __uint32 firstbyte=tracknum*samplesinblock*bytespersam; + __uint32 whichbyte=firstbyte; + + int samval; + for (unsigned int sam=0;sam2) { + // multi track + // use only 24 out of 32 bit + samval = (audiobuf[tracknum][whichsam+(action-3)])/256; + } else { + if (action<2) + { + samval=(audiobuf[tracknum][whichsam]); + } else { + // action=2 (mono track). + if (trackchans==1) + { + // use the only track + samval=(audiobuf[tracknum][whichsam])/256; + } + else { + // convert multiple tracks to 1 mono track + samval=0; + for (unsigned int whichchan=0;whichchan>8) & 0xff) << " " << ((samval>>16) & 0xff) <<"//"; + if (sam==0) { + cout << "writing to byte " << whichbyte << " of audiodata " <>8) & 0xff; + audiodata[whichbyte+2]=(unsigned char)(samval>>16) & 0xff; + whichbyte+=bytespersam; + } + // cout << endl; + + if (transfer_cancel==1) { + //ui_refresh("tohd24_cancel2"); + break; + } + } + + // finally we write the audio. the hd24 library will make sure only the relevant + // tracks will be overwritten and the rest are protected. + #if (HD24TRANSFERDEBUG==1) + cout << "1st 30 bytes of track: " << endl; + for (unsigned int fbyte=0; fbyte<30; fbyte++) { + cout << audiodata[samplesinblock+fbyte] << " "; + } + cout << endl; + #endif + //int writesams= (result was not used) + job->targetsong()->putmtrackaudiodata( + samplenum+startoffset, + samplesinblock, + &audiodata[0], + hd24song::WRITEMODE_COPY + ); + + totbytestransferred+=(samplesinblock*bytespersam); + + __uint32 pct; // to use for display percentage + __uint32 oldpct=0; // to use for display percentage + double dblpct; // to use for ETA calculation + #if (HD24TRANSFERDEBUG==1) + cout << "about to calc pct" << endl; + cout << "totbytestransferred=" << totbytestransferred; + cout << ", currbytestransferred=" << bytestransferred; + cout << ", totbytestotransfer=" << totbytestotransfer; + cout << endl; + #endif + + if (translen<100000) { + pct=(__uint32)(((totbytestransferred+bytestransferred)*100)/(totbytestotransfer)); + } else { + pct=(__uint32)((totbytestransferred+bytestransferred)/(totbytestotransfer/100)); + } + #if (HD24TRANSFERDEBUG==1) + cout << "about to calc pct2" << endl; + #endif + if (translen<100000) { + dblpct=(((totbytestransferred+bytestransferred)*100)/(totbytestotransfer)); + } else { + dblpct=((totbytestransferred+bytestransferred)/(totbytestotransfer/100)); + } + + #if (HD24TRANSFERDEBUG==1) + cout << "computed pct " << samplenum << endl; + #endif + time (&endtime); + olddifseconds=difseconds; + difseconds=(long long int)difftime(endtime,starttime); + + if ((pct!=oldpct) || ((difseconds-olddifseconds)>=1)) + { + /* update on percentage change, and also every + so many samples (to allow frequent enough + screen updates with large audio files) */ + oldpct=pct; + + string* pctmsg=new string("Transferring audio to HD24... %d%%"); + // TODO: Estimated time remaining goes here + setstatus(ui,pctmsg,pct); + delete pctmsg; + } + + // fl_check(); covered by setstatus + } + + // fl_check(); covered by setstatus + if (job->smptegen!=NULL) + { + // TODO: move to job destructor? + delete job->smptegen; + job->smptegen=NULL; + } + if (audiodata!=NULL) + { + free (audiodata); + audiodata=NULL; + } + for (unsigned int bufnum=0;bufnumtargetsong()->stoprecord(); + + for (unsigned int chnum=1;chnum<=job->targetsong()->logical_channels();chnum++) { + job->targetsong()->trackarmed(chnum,false); + } + this->closeinputfiles((SNDFILE**)&(job->filehandle[0]),job->targetsong()->logical_channels()); + return totbytestransferred; +} + 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 @@ +#ifndef __hd24transferengine_h__ +#define __hd24transferengine_h__ + +class MixerControl; + +#include +#include +#include +#include +#include +class hd24transferjob +{ +friend class hd24transferengine; +private: + long long llsizelimit; /* to hold max filesize for autosplit */ + int mixleft; + int mixright; + int m_selectedformat; + hd24fs* jobsourcefs; + hd24song* jobsourcesong; + hd24fs* jobtargetfs; + hd24song* jobtargetsong; + __uint32 m_startoffset; + __uint32 m_endoffset; + SNDFILE* filehandle[24]; /* todo: implement as hd24sndfile* */ + char* filepath[24]; /* one full file path/name per track + mainly to be used for export to hd24 */ + bool have_smpte; + int m_trackaction[24]; + SMPTEgenerator* smptegen; +public: + + string* m_projectdir; + int usecustomrate; // 1 to stamp export with custom sample rate + // 0 to keep song sample rate + __uint32 stamprate; //sample rate to use if usecustomrate==1 + int wantsplit; + int* trackselected; + hd24transferjob(); + ~hd24transferjob(); + void init_vars(); + + void sizelimit(__sint64 llsizelimit); + __sint64 sizelimit(); + + __uint32 startoffset(); + __uint32 endoffset(); + void startoffset(__uint32 newoff); + void endoffset(__uint32 newoff); + + void projectdir(const char* projectdir); + const char* projectdir(); + void selectedformat(int format); + int selectedformat(); + hd24fs* sourcefs(); + hd24fs* targetfs(); + hd24song* sourcesong(); + hd24song* targetsong(); + void sourcefs(hd24fs* fs); + void targetfs(hd24fs* fs); + void sourcesong(hd24song* song); + void targetsong(hd24song* song); + char* sourcefilename(int base1tracknum); + void sourcefilename(int base1tracknum,const char* name); + void trackaction(int base1tracknum,int action); + int trackaction(int base1tracknum); +}; + +class hd24transferengine +{ +private: + void* ui; + + MixerControl* transfermixer; + hd24transferjob* job; + + __uint32 songnum; + __uint32 totsongs; + __sint64 totbytestotransfer; + __sint64 totbytestransferred; + + int prefix; + int transfer_cancel; + int trackspergroup; + int* audiobuf[24]; /* for libsndfile int reading from file */ + bool isfirstchanofgroup[24]; /* for exporting stereo pairs/groups of channels */ + bool islastchanofgroup[24]; /* for exporting stereo pairs/groups of channels */ + + void setstatus(void* ui,string* message,double percent); + + void openbuffers(unsigned char** audiobuf,unsigned int channels,unsigned int bufsize); + void closebuffers(unsigned char** audiobuf,unsigned int channels); + void writerawbuf(hd24sndfile* filehandle,unsigned char* buf,long subblockbytes); + void flushbuffer(hd24sndfile** filehandle,unsigned char** buffer,__uint32 flushbytes,unsigned int channels); + + + bool overwritegivesproblems(hd24song* thesong,int partnum); + bool confirmfileoverwrite(); // perform interactive/GUI callback + // to confirm if file overwriting is OK + bool anyfilesexist(hd24song* thesong); + void transfer_in_progress(bool active); + + time_t starttime; // these are for benchmarking the transfer + time_t endtime; + + /* Regarding populating list of supported file formats + TODO: Move to a separate class? + */ + int formatcount; + void populate_formatlist(); + vector* m_format_outputextension; + vector* m_format_shortdesc; + int m_format_outputformat[100]; + int m_format_outputchannels[100]; + int m_format_bitdepth[100]; + bool m_format_sndfile[100]; + string* m_lasterror; + +public: + SoundFileWrapper* soundfile; + bool (*uiconfirmfunction)(void* ui,const char*); + void (*setstatusfunction)(void* ui,const char*,double progress_pct); + + void set_ui(void* p_ui); + + hd24transferengine(); + ~hd24transferengine(); + + void mixer(MixerControl* m_mixer); + MixerControl* mixer(); + + void lasterror(const char* errormessage); + string* lasterror(); + + int supportedformatcount(); + int format_outputchannels(int i); + const char* getformatdesc(int formatnum); + + void trackselected(__uint32 base0tracknum,bool select); + bool trackselected(__uint32 base0tracknum); + + void mixleft(bool select); + bool mixleft(); + void mixright(bool select); + bool mixright(); + + void init_vars(); + void prepare_transfer_to_pc( + __uint32 songnum, __uint32 totsongs, + __sint64 totbytestotransfer, + __sint64 totbytestransferred, + int wantsplit,__uint32 prefix); + + __sint64 transfer_to_pc(); + __sint64 transfer_to_hd24(); + + bool openinputfiles(SNDFILE** filehandle,SF_INFO* sfinfoin,unsigned int channels); + void closeinputfiles(SNDFILE** filehandle,unsigned int channels); + bool dontopenoutputfiles(hd24sndfile** filehandle,unsigned int channels,unsigned int partnum,int prefix); //HACK + + bool openoutputfiles(hd24sndfile** filehandle,unsigned int channels,unsigned int partnum,int prefix); + void closeoutputfiles(hd24sndfile** filehandle,unsigned int channels); + string* generate_filename(int tracknum,int partnum,int prefix); + void sizelimit(__sint64 llsizelimit); + __sint64 sizelimit(); + void projectdir(const char* projectdir); + const char* projectdir(); + + void selectedformat(int format); + int selectedformat(); + + void sourcesong(hd24song* newsong); + hd24song* sourcesong(); + void targetsong(hd24song* newsong); + hd24song* targetsong(); + + __uint32 startoffset(); + __uint32 endoffset(); + void startoffset(__uint32 newoff); + void endoffset(__uint32 newoff); + char* sourcefilename(int base1tracknum); + void sourcefilename(int base1tracknum,const char* name); + void trackaction(int base1tracknum,int action); + int trackaction(int base1tracknum); + +}; + +#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 @@ +#define UTILDEBUG 0 +#ifdef DARWIN +# define creat64 creat +# define open64 open +# define lseek64 lseek +# define pread64 pread +# define pwrite64 pwrite +#endif + +#if defined(LINUX) || defined(DARWIN) +# define PRINTAPP "lp" +#endif + +#ifdef WINDOWS +# include +# include +# define PRINTAPP "print" +# define popen _popen +# define pclose _pclose +#else +# include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "convertlib.h" +#include "hd24utils.h" +#include "memutils.h" +#define _LARGE_FILES +#define LARGE_FILES +#define LARGEFILE64_SOURCE +#define _FILE_OFFSET_BITS 64 +#define FILE_OFFSET_BITS 64 +#define SECTORSIZE 512 +#define FSINFO_VERSION_MAJOR 0x8 +#define FSINFO_VERSION_MINOR 0x9 +#define FSINFO_BLOCKSIZE_IN_SECTORS 0x10 +#define FSINFO_AUDIOBLOCKS_PER_CLUSTER 0x14 +#define FSINFO_STARTSECTOR_FAT 0x38 +#define FSINFO_NUMSECTORS_FAT 0x3c +#define FSINFO_CLUSTERS_ON_DISK 0x44 +#define FSINFO_MAXPROJECTS 0x50 +#define FSINFO_MAXSONGSPERPROJECT 0x54 +#define FSINFO_DATAAREA 0x7c +#define DRIVEINFO_VOLUME 0x1b8 +#define DRIVEINFO_PROJECTCOUNT 0x0c +#define DRIVEINFO_LASTPROJ 0x10 +#define DRIVEINFO_PROJECTLIST 0x20 + +void hd24utils::gencatalog_showsongs(hd24project* currentproj,string* strcatalog) +{ + if (currentproj==NULL) { + return; + } + if (strcatalog==NULL) { + return; + } + int numsongs=currentproj->songcount(); + *strcatalog+=" ======================================================================\n"; + if (numsongs==0) { + *strcatalog+=" There are no songs in this project.\n"; + return; + } + hd24song* currsong=NULL; + for (int i=1; i<=numsongs; i++) { + currsong=currentproj->getsong(i); + if (currsong==NULL) continue; + + *strcatalog+=" "; + *strcatalog+=" "; + if (i<10) { + *strcatalog+=" "; + } + string* songnum=Convert::int2str(i); + *strcatalog+=*songnum; + *strcatalog+=": "; + delete songnum; + + string* currsname=currsong->songname(); + string* pad=Convert::padright(*currsname,35," "); + delete(currsname); + *strcatalog+=*pad; + delete pad; + string* dur=currsong->display_duration(); + *strcatalog+=*dur; + delete dur; + *strcatalog+= ", " ; + + string* chans=Convert::int2str(currsong->logical_channels()); + string* chans2=Convert::padleft(*chans,2," "); + *strcatalog+=*chans; + delete chans; + delete chans2; + *strcatalog+="ch. "; + + string* samrate=Convert::int2str(currsong->samplerate()); + *strcatalog+=*samrate; + delete samrate; + *strcatalog+=" Hz"; + + + if (currsong->iswriteprotected()) + { + *strcatalog+="*"; + } + + *strcatalog+="\n"; + + delete currsong; + currsong=NULL; + } + return; +} + +void hd24utils::gencatalog_showprojects(hd24fs* currenthd24,string* strcatalog) +{ + int numprojs=currenthd24->projectcount(); + hd24project* currproj=NULL; + for (int i=1; i<=numprojs; i++) + { + currproj=currenthd24->getproject(i); + + *strcatalog+=" ======================================================================\n"; + *strcatalog+=" Project "; + string* projnum=Convert::int2str(i); + *strcatalog+=*projnum; + delete projnum; + *strcatalog+=": "; + + string* currpname=currproj->projectname(); + *strcatalog+= *currpname; + delete(currpname); + + *strcatalog+="\n"; // << endl; + gencatalog_showsongs (currproj,strcatalog); //to_out); + delete(currproj); + } + +} + +int hd24utils::gencatalog(hd24fs* currenthd24,string* strcatalog) +{ + + time_t currenttime; + struct tm timestamp; + char timebuf[80]; + time(¤ttime); + timestamp = *localtime(¤ttime); + strftime(timebuf,sizeof(timebuf),"%a %Y-%m-%d %H:%M:%S %Z", ×tamp); + *strcatalog+= " Catalog timestamp : "; + *strcatalog+= timebuf ; + *strcatalog+="\n"; + + *strcatalog+=" Volume name : "; + string* volname=currenthd24->volumename(); + *strcatalog+=*volname; + delete volname; + *strcatalog+="\n"; + + *strcatalog+=" Number of projects : "; + string* pcount=Convert::int2str(currenthd24->projectcount()); + *strcatalog+=*pcount; + delete pcount; + + *strcatalog+="\n"; + gencatalog_showprojects(currenthd24,strcatalog); + return 0; +} + +string* hd24utils::savecatalog(hd24fs* currenthd24,string* filename) +{ + string* error=new string(""); + + // gencatalog + string* catalog=new string(""); + + if (hd24utils::gencatalog(currenthd24,catalog)!=0) + { + *error+="Error generating catalog."; + return error; + } + fstream to_out(filename->c_str(),ios::out); + if (to_out==NULL) + { + *error+="Cannot write catalog."; + return error; + } + to_out << *catalog ; + + to_out.flush(); + to_out.close(); + return NULL; +} + +string* hd24utils::printcatalog(hd24fs* currenthd24) +{ + + string* error=new string(""); + string catname="_hd24cat.txt"; + + + // gencatalog + string* catalog=new string(""); + + if (hd24utils::gencatalog(currenthd24,catalog)!=0) + { + *error+="Error generating catalog."; + return error; + } + fstream to_out(catname.c_str(),ios::out); + if (to_out==NULL) + { + *error+="Cannot write catalog."; + return error; + } + *catalog += "\f\n"; // form feed + to_out << *catalog ; + + to_out.flush(); + to_out.close(); + +#ifdef WINDOWS + SHELLEXECUTEINFO ShExecInfo = {0}; + ShExecInfo.cbSize = sizeof (SHELLEXECUTEINFO); + ShExecInfo.fMask = SEE_MASK_NOCLOSEPROCESS; //SEE_MASK_INVOKEIDLIST; + ShExecInfo.hwnd = NULL; + ShExecInfo.lpVerb="print"; + ShExecInfo.lpFile=catname.c_str(); + ShExecInfo.lpParameters = ""; + ShExecInfo.lpDirectory=NULL; + ShExecInfo.nShow = SW_HIDE; + ShExecInfo.hInstApp = NULL; + ShellExecuteEx(&ShExecInfo); + WaitForSingleObject(ShExecInfo.hProcess,INFINITE); + unlink (catname.c_str()); +#else + char s[1024]; + string* catcmd = new string (PRINTAPP); + *catcmd += " "; + *catcmd += catname; + *catcmd += " 2>&1"; + FILE *fp = popen(catcmd->c_str() , "r"); + while (fgets(s, sizeof(s)-1, fp)) + { + *error += s; + } + pclose(fp); + unlink (catname.c_str()); +#endif + return error; +} + + +void hd24utils::interlacetobuffer(unsigned char* sourcebuf,unsigned char* targetbuf, + __uint32 totbytes,__uint32 bytespersam,__uint32 trackwithingroup,__uint32 trackspergroup) +{ + __uint32 samplenum; + __uint32 totsams=totbytes/bytespersam; + __uint32 trackoff=(trackwithingroup*bytespersam); + __uint32 q=0; + // unroll loop for bytespersam=1,2,3 + switch (bytespersam) + { + case 3: + for (samplenum=0;samplenumc_str(),O_WRONLY); +#endif +#ifdef WINDOWS + FSHANDLE handle=CreateFile(outputfilename->c_str(),GENERIC_WRITE|GENERIC_READ, + FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); + if (hd24fs::isinvalidhandle(handle)) { + handle=CreateFile(outputfilename->c_str(),GENERIC_WRITE|GENERIC_READ, + FILE_SHARE_READ|FILE_SHARE_WRITE, + NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL); + } + + #endif + if (hd24fs::isinvalidhandle(handle)) { + // cout << "Cannot open file "<=MULTISECTOR) { + numsectors=MULTISECTOR; + } + if (currenthd24!=NULL) { + currenthd24->readsector_noheader(currenthd24,i,bootblock); // raw reading + } +#if defined(LINUX) || defined(DARWIN) + __uint64 targetoff=i; + targetoff-=firstsector; + targetoff*=512; + ssize_t byteswritten=0; + if (currenthd24!=NULL) { + byteswritten=pwrite64(handle,bootblock,512,targetoff); + } else { + byteswritten=pwrite64(handle,bootblock,512*numsectors,targetoff); + i+=(numsectors-1); + } +#endif +#ifdef WINDOWS + //DWORD dummy; + //long bytes=0; + __uint64 targetoff=i; + targetoff-=firstsector; + __uint64 byteswritten=0; + if (currenthd24!=NULL) { + byteswritten=currenthd24->writesectors(handle,targetoff,bootblock,1); + } else { + byteswritten=currenthd24->writesectors(handle,targetoff,bootblock,numsectors); + i+=(numsectors-1); + } +#endif + if (byteswritten==0) { +#if defined(LINUX) || defined(DARWIN) + close (handle); +#endif +#ifdef WINDOWS + CloseHandle(handle); +#endif + return 1; + } + if (message!=NULL) { + if (q%1000==0) { + sprintf(message,"Saving sector %ld of %ld",i,(endsector+1)); + + // cout << i << endl; + Fl::wait(0); + } + } + } +#if defined(LINUX) || defined(DARWIN) + close (handle); + chmod(outputfilename->c_str(),0664); +#endif +#ifdef WINDOWS + CloseHandle(handle); +#endif + + return 0; +} + +int hd24utils::savedriveimage(hd24fs* currenthd24,string* imagefilename,char* message,int* cancel) { + unsigned long firstsector=0; + unsigned long endsector=currenthd24->getlastsectornum(); + return savedrivesectors(currenthd24,imagefilename,firstsector,endsector,message,cancel); +} + +int hd24utils::newdriveimage(string* imagefilename,__uint32 endsector,char* message,int* cancel) { + if (endsector<1353964) + { + // requested drive size is less than possible minimum size + return -1; + } + + unsigned long firstsector=0; +#if (UTILDEBUG==1) +cout << "about to save drive sectors" <write_enable(); +#if (UTILDEBUG==1) +cout << "quickformatting fs" <quickformat(message); +#if (UTILDEBUG==1) + cout << "format result=" << *message << endl; +cout << "deleting format fs object" <find(pathsep->c_str()); + if (idx==string::npos) { + last=1; + exepath=new string(strpath->c_str()); + exename=new string(strpath->c_str()); + *strpath=""; + } else { + exepath=new string(strpath->substr(0,idx)); + exename=new string(strpath->substr(0,idx)); + *strpath=strpath->substr(idx+1); + } +#if (UTILDEBUG==1) + cout << "exepath= " << *exepath << endl; +#endif + if (exepath->substr(exepath->length()-1,1)!=PATHSLASH) { + *exepath+=PATHSLASH; + } + if (exename->substr(exename->length()-1,1)!=PATHSLASH) { + *exename+=PATHSLASH; + } + + *exename+=rawname; +#if (UTILDEBUG==1) + cout << "test if file " << exename->c_str() << " exists" << endl; +#endif + if (hd24utils::fileExists(exename->c_str())) { + strncpy(result,exepath->c_str(),2048); + if (exename!=NULL) { + delete exename; + exename=NULL; + } + if (exepath!=NULL) { + delete exepath; + exepath=NULL; + } + if (strpath!=NULL) { + delete strpath; + strpath=NULL; + } + if (pathsep!=NULL) { + delete pathsep; + pathsep=NULL; + } + return ; + } + if (exename!=NULL) { + delete exename; + exename=NULL; + } + if (exepath!=NULL) { + delete exepath; + exepath=NULL; + } + } + + if (strpath!=NULL) { + delete strpath; + strpath=NULL; + } + if (pathsep!=NULL) { + delete pathsep; + pathsep=NULL; + } + + result[0]=(char)0; + return; +} + +bool hd24utils::fileExists(const char* strFilename) { + struct stat stFileInfo; + int intStat; + + // Attempt to get the file attributes + intStat = stat(strFilename,&stFileInfo); + if(intStat == 0) + { + // We were able to get the file attributes + // so the file obviously exists. + return true; + } + // We were not able to get the file attributes. + // This may mean that we don't have permission to + // access the folder which contains this file. If you + // need to do that level of checking, lookup the + // return values of stat which will give you + // more details on why stat failed. + return false; +} + +string* hd24utils::getlastdir(string which) +{ + string* whichdir; + char buffer[FL_PATH_MAX]; + + Fl_Preferences* userprefs=new Fl_Preferences(Fl_Preferences::USER, "HD24","HD24connect" ); + /* Attempt to find last used project dir */ + if (userprefs->entryExists(which.c_str())) { + userprefs->get(which.c_str(),buffer,".",FL_PATH_MAX); + whichdir=new string(buffer); + } else { + whichdir=new string("."); + } + delete userprefs; + return whichdir; +} + +void hd24utils::setlastdir(string which,const char* newdir) +{ + Fl_Preferences* userprefs=new Fl_Preferences(Fl_Preferences::USER, "HD24","HD24connect" ); + userprefs->set(which.c_str(),newdir); + // cout << "just set " << which << " to " << newdir << endl; + delete userprefs; +} 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 @@ +#ifndef __hd24utils_h__ +#define __hd24utils_h__ +#ifndef WINDOWS +#define PATHSLASH "/" +# include +# include +#else +#define PATHSLASH "\\" +# include +# include +# include +# define FSHANDLE HANDLE +# define FSHANDLE_INVALID INVALID_HANDLE_VALUE +#endif + +#if defined(LINUX) || defined(DARWIN) +# define FSHANDLE int +# define FSHANDLE_INVALID -1 +#endif + +#include +#include +#include +#include +#include "convertlib.h" +#include "memutils.h" +#include + +using namespace std; +class hd24fs; +class hd24project; +class hd24song; + +class hd24utils +{ + friend class hd24fs; + friend class hd24project; + friend class hd24song; + private: + // static void savecatalog_showprojects(hd24fs* currenthd24,fstream & to_out); + // static void savecatalog_showsongs(hd24project* currentproj,fstream & to_out); + static void gencatalog_showprojects(hd24fs* currenthd24,string* strcatalog); + static void gencatalog_showsongs(hd24project* currentproj,string* strcatalog); + + public: + // static int savecatalog(hd24fs* currenthd24,string* headerfilename,bool toprint); + // static int gencatalog(hd24fs* currenthd24,string* headerfilename,bool toprint); + static string* savecatalog(hd24fs* currenthd24,string* filename); + static void findfile(const char* rawfilename, const char* searchpath, char* result); + static int gencatalog(hd24fs* currenthd24,string* strcatalog); + static string* printcatalog(hd24fs* currenthd24); + static int saveheader(hd24fs* currenthd24,string* headerfilename); + static int savedriveimage(hd24fs* currenthd24,string* imagefilename, char* message,int* cancel); + static int newdriveimage(string* imagefilename,__uint32 endsector,char* message,int* cancel); + static int savedrivesectors(hd24fs* currenthd24,string* imagefilename,unsigned long startsector,unsigned long endsector,char* message,int* cancel); + static void interlacetobuffer(unsigned char* sourcebuf,unsigned char* targetbuf, __uint32 totbytes,__uint32 bytespersam,__uint32 trackwithingroup,__uint32 trackspergroup); + static bool dirExists(const char * pszDirName); + static bool fileExists(const char * filename); + static string* getlastdir(string which); + static void dumpsector (const char* buffer); + static void setlastdir(string which,const char* newdir); +}; + +#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 @@ +#include +#include +#include "memutils.h" +#define MEMDEBUG 0 +void* memutils::mymalloc(const char* wherefrom,__uint32 elcount,__uint32 elsize) +{ + void* q=calloc(elcount,elsize); +#if (MEMDEBUG==1) + cout << "ALLOC: " << wherefrom + <<" allocated " + << elcount<<" bytes at " << q << endl; +#else + wherefrom=NULL; +#endif + return q; +} + +void memutils::myfree(const char* wherefrom,void* freewhat) +{ +#if (MEMDEBUG==1) + cout << "FREE: "<< wherefrom <<" free bytes at " << freewhat << endl; +#else + wherefrom=NULL; +#endif + free(freewhat); +} + 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 @@ +#ifndef __memutils_h__ +#define __memutils_h__ + +using namespace std; +#include + +class memutils +{ +public: + static void* mymalloc(const char* wherefrom,__uint32 elcount,__uint32 elsize); + static void myfree(const char* wherefrom,void* freewhat); +}; + +#endif + 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 @@ +#include "nojack.h" +#ifndef NULL +#define NULL 0 +#endif +jack_client_t *jack_client_new (const char *client_name) { return NULL; }; +int jack_client_close (jack_client_t *client) { return 0; }; +int jack_client_name_size(void) { return 0; }; +int jack_internal_client_new (const char *client_name, const char *so_name, + const char *so_data) { return 0; }; +void jack_internal_client_close (const char *client_name) { return; } +int jack_is_realtime (jack_client_t *client) { return 0; } +void jack_on_shutdown (jack_client_t *client, void (*function)(void *arg), void *arg) { return; } +int jack_set_process_callback (jack_client_t *client, + JackProcessCallback process_callback, + void *arg) {return 0; } +int jack_set_thread_init_callback (jack_client_t *client, + JackThreadInitCallback thread_init_callback, + void *arg) { return 0;} +int jack_set_freewheel_callback (jack_client_t *client, + JackFreewheelCallback freewheel_callback, + void *arg) { return 0;} +int jack_set_freewheel(jack_client_t* client, int onoff) { return 0;} + +int jack_set_buffer_size (jack_client_t *client, jack_nframes_t nframes) {return 0;} +int jack_set_buffer_size_callback (jack_client_t *client, + JackBufferSizeCallback bufsize_callback, + void *arg) {return 0;}; +int jack_set_sample_rate_callback (jack_client_t *client, + JackSampleRateCallback srate_callback, + void *arg) { return 0;}; +int jack_transport_query(jack_client_t *x,__uint64* y) {return 0;} +int jack_set_port_registration_callback (jack_client_t *, + JackPortRegistrationCallback + registration_callback, void *arg) {return 0;}; +int jack_set_graph_order_callback (jack_client_t *, JackGraphOrderCallback graph_callback, void *) {return 0;}; + +int jack_set_xrun_callback (jack_client_t *, JackXRunCallback xrun_callback, void *arg) { return 0;}; +int jack_activate (jack_client_t *client) {return 0;}; +int jack_deactivate (jack_client_t *client) {return 0;}; +jack_port_t *jack_port_register (jack_client_t *client, + const char *port_name, + const char *port_type, + unsigned long flags, + unsigned long buffer_size) { return NULL; } +int jack_port_unregister (jack_client_t *, jack_port_t *) { return 0; } +void *jack_port_get_buffer (jack_port_t *, jack_nframes_t) { return NULL;} +const char *jack_port_name (const jack_port_t *port) { return NULL; } +const char *jack_port_short_name (const jack_port_t *port) { return NULL; } +int jack_port_flags (const jack_port_t *port) { return 0;} +const char *jack_port_type (const jack_port_t *port) { return 0;} + +int jack_port_is_mine (const jack_client_t *, const jack_port_t *port) {return 0;}; + +int jack_port_connected (const jack_port_t *port); +int jack_port_connected_to (const jack_port_t *port, + const char *port_name); +const char **jack_port_get_connections (const jack_port_t *port); +const char **jack_port_get_all_connections (const jack_client_t *client, + const jack_port_t *port); +int jack_port_tie (jack_port_t *src, jack_port_t *dst); +int jack_port_untie (jack_port_t *port); +int jack_port_lock (jack_client_t *, jack_port_t *); +int jack_port_unlock (jack_client_t *, jack_port_t *); +jack_nframes_t jack_port_get_latency (jack_port_t *port); +jack_nframes_t jack_port_get_total_latency (jack_client_t *, + jack_port_t *port); +void jack_port_set_latency (jack_port_t *, jack_nframes_t); +int jack_port_set_name (jack_port_t *port, const char *port_name); +int jack_port_request_monitor (jack_port_t *port, int onoff); +int jack_port_ensure_monitor (jack_port_t *port, int onoff); +int jack_port_monitoring_input (jack_port_t *port); +int jack_connect (jack_client_t *, + const char *source_port, + const char *destination_port); +int jack_disconnect (jack_client_t *, + const char *source_port, + const char *destination_port); +int jack_port_disconnect (jack_client_t *, jack_port_t *); +int jack_port_name_size(void); + +/** + * @return the maximum number of characters in a JACK port type name + * including the final NULL character. This value is a constant. + */ +int jack_port_type_size(void); + +/** + * @return the sample rate of the jack system, as set by the user when + * jackd was started. + */ +jack_nframes_t jack_get_sample_rate (jack_client_t *); + +/** + * @return the current maximum size that will ever be passed to the @a + * process_callback. It should only be used *before* the client has + * been activated. This size may change, clients that depend on it + * must register a @a bufsize_callback so they will be notified if it + * does. + * + * @see jack_set_buffer_size_callback() + */ +jack_nframes_t jack_get_buffer_size (jack_client_t *); + +/** + * @param port_name_pattern A regular expression used to select + * ports by name. If NULL or of zero length, no selection based + * on name will be carried out. + * @param type_name_pattern A regular expression used to select + * ports by type. If NULL or of zero length, no selection based + * on type will be carried out. + * @param flags A value used to select ports by their flags. + * If zero, no selection based on flags will be carried out. + * + * @return a NULL-terminated array of ports that match the specified + * arguments. The caller is responsible for calling free(3) any + * non-NULL returned value. + * + * @see jack_port_name_size(), jack_port_type_size() + */ +const char **jack_get_ports (jack_client_t *, + const char *port_name_pattern, + const char *type_name_pattern, + unsigned long flags); + +/** + * @return address of the jack_port_t named @a port_name. + * + * @see jack_port_name_size() + */ +jack_port_t *jack_port_by_name (jack_client_t *, const char *port_name); + +/** + * @return address of the jack_port_t of a @a port_id. + */ +jack_port_t *jack_port_by_id (const jack_client_t *client, + jack_port_id_t port_id); + +/** + * Old-style interface to become the timebase for the entire JACK + * subsystem. + * + * @deprecated This function still exists for compatibility with the + * earlier transport interface, but it does nothing. Instead, see + * transport.h and use jack_set_timebase_callback(). + * + * @return ENOSYS, function not implemented. + */ +int jack_engine_takeover_timebase (jack_client_t *); + +/** + * @return the time in frames that has passed since the JACK server + * began the current process cycle. + */ +jack_nframes_t jack_frames_since_cycle_start (const jack_client_t *); + +/** + * @return an estimate of the current time in frames. This is a + * running counter, no significance should be attached to its value, + * but it can be compared to a previously returned value. + */ +jack_nframes_t jack_frame_time (const jack_client_t *); + +/** + * @return the frame_time after the last processing of the graph + * this is only to be used from the process callback. + * + * This function can be used to put timestamps generated by + * jack_frame_time() in correlation to the current process cycle. + */ +jack_nframes_t jack_last_frame_time (const jack_client_t *client); + + +/** + * @return the current CPU load estimated by JACK. This is a running + * average of the time it takes to execute a full process cycle for + * all clients as a percentage of the real time available per cycle + * determined by the buffer size and sample rate. + */ +float jack_cpu_load (jack_client_t *client); + +/** + * Set the directory in which the server is expected + * to have put its communication FIFOs. A client + * will need to call this before calling + * jack_client_new() if the server was started + * with arguments telling it to use a non-standard + * directory. + * + * @deprecated This function is deprecated. Don't use in new programs + * and remove it in old programs. + */ +void jack_set_server_dir (const char *path); + +/** + * @return the pthread ID of the thread running the JACK client side + * code. + */ +pthread_t jack_client_thread_id (jack_client_t *); + +/** + * Display JACK error message. + * + * Set via jack_set_error_function(), otherwise a JACK-provided + * default will print @a msg (plus a newline) to stderr. + * + * @param msg error message text (no newline at end). + */ +extern void (*jack_error_callback)(const char *msg); + +/** + * Set the @ref jack_error_callback for error message display. + * + * The JACK library provides two built-in callbacks for this purpose: + * default_jack_error_callback() and silent_jack_error_callback(). + */ +void jack_set_error_function (void (*func)(const char *)); +__uint64 jack_get_current_transport_frame(void* client) { return 0; } +void jack_transport_stop (void * dummy) { return; }; +void jack_transport_start (void * dummy) { return; }; +void jack_transport_locate (void * dummy,int x) { return; }; +//void* jack_port_register (void* dummy,const void* dum2,int q,int y,int z) {return NULL;}; +#define JACK_DEFAULT_AUDIO_TYPE 0 + 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 @@ +/* + Copyright (C) 2001 Paul Davis + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + $Id: jack.h,v 1.64 2004/07/15 03:07:28 trutkin Exp $ +*/ + +#ifndef __jack_h__ +#define __jack_h__ + +#include "config.h" +#define __int64 long long +#ifdef __cplusplus +extern "C" { +#endif +#define jack_client_t void +#define jack_nframes_t __uint64 +#define jack_position_t __uint64 +#define jack_default_audio_sample_t int +#define jack_port_t void* +#define JackPortIsOutput 0 +#define JackPortIsInput 0 +typedef int(*JackProcessCallback)(__uint64, int,void*); +#define JackThreadInitCallback void* +#define JackPortRegistrationCallback void* +#define JackGraphOrderCallback void* +#define JackXRunCallback void* +#define JackFreewheelCallback void* +#define JackBufferSizeCallback void* +#define JackSampleRateCallback void* +#define jack_port_id_t void* +#define jack_transport_state_t int +#define JackTransportStopped 0 +#define pthread_t void* +jack_client_t *jack_client_new (const char *client_name); +int jack_client_close (jack_client_t *client); +int jack_client_name_size(void); +int jack_internal_client_new (const char *client_name, const char *so_name, + const char *so_data); +void jack_internal_client_close (const char *client_name); +int jack_is_realtime (jack_client_t *client); +void jack_on_shutdown (jack_client_t *client, void (*function)(void *arg), void *arg) ; +int jack_set_process_callback (jack_client_t *client, + JackProcessCallback process_callback, + void *arg) ; +int jack_set_thread_init_callback (jack_client_t *client, + JackThreadInitCallback thread_init_callback, + void *arg) ; +int jack_set_freewheel_callback (jack_client_t *client, + JackFreewheelCallback freewheel_callback, + void *arg) ; +int jack_set_freewheel(jack_client_t* client, int onoff) ; + +int jack_set_buffer_size (jack_client_t *client, jack_nframes_t nframes) ; +int jack_set_buffer_size_callback (jack_client_t *client, + JackBufferSizeCallback bufsize_callback, + void *arg); +int jack_set_sample_rate_callback (jack_client_t *client, + JackSampleRateCallback srate_callback, + void *arg); +int jack_transport_query(jack_client_t *x,__uint64* y); +int jack_set_port_registration_callback (jack_client_t *, + JackPortRegistrationCallback + registration_callback, void *arg) ; +int jack_set_graph_order_callback (jack_client_t *, JackGraphOrderCallback graph_callback, void *) ; + +int jack_set_xrun_callback (jack_client_t *, JackXRunCallback xrun_callback, void *arg) ; +int jack_activate (jack_client_t *client) ; +int jack_deactivate (jack_client_t *client) ; +jack_port_t *jack_port_register (jack_client_t *client, + const char *port_name, + const char *port_type, + unsigned long flags, + unsigned long buffer_size) ; +int jack_port_unregister (jack_client_t *, jack_port_t *) ; +void *jack_port_get_buffer (jack_port_t *, jack_nframes_t) ; +const char *jack_port_name (const jack_port_t *port) ; +const char *jack_port_short_name (const jack_port_t *port) ; +int jack_port_flags (const jack_port_t *port) ; +const char *jack_port_type (const jack_port_t *port) ; + +int jack_port_is_mine (const jack_client_t *, const jack_port_t *port) ; + +/** + * @return number of connections to or from @a port. + * + * @pre The calling client must own @a port. + */ +int jack_port_connected (const jack_port_t *port); + +/** + * @return TRUE if the locally-owned @a port is @b directly connected + * to the @a port_name. + * + * @see jack_port_name_size() + */ +int jack_port_connected_to (const jack_port_t *port, + const char *port_name); + +/** + * @return a null-terminated array of full port names to which the @a + * port is connected. If none, returns NULL. + * + * The caller is responsible for calling free(3) on any non-NULL + * returned value. + * + * @param port locally owned jack_port_t pointer. + * + * @see jack_port_name_size(), jack_port_get_all_connections() + */ +const char **jack_port_get_connections (const jack_port_t *port); + +/** + * @return a null-terminated array of full port names to which the @a + * port is connected. If none, returns NULL. + * + * The caller is responsible for calling free(3) on any non-NULL + * returned value. + * + * This differs from jack_port_get_connections() in two important + * respects: + * + * 1) You may not call this function from code that is + * executed in response to a JACK event. For example, + * you cannot use it in a GraphReordered handler. + * + * 2) You need not be the owner of the port to get information + * about its connections. + * + * @see jack_port_name_size() + */ +const char **jack_port_get_all_connections (const jack_client_t *client, + const jack_port_t *port); + +/** + * A client may call this on a pair of its own ports to + * semi-permanently wire them together. This means that + * a client that wants to direct-wire an input port to + * an output port can call this and then no longer + * have to worry about moving data between them. Any data + * arriving at the input port will appear automatically + * at the output port. + * + * The 'destination' port must be an output port. The 'source' + * port must be an input port. Both ports must belong to + * the same client. You cannot use this to tie ports between + * clients. That is what a connection is for. + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_port_tie (jack_port_t *src, jack_port_t *dst); + +/** + * This undoes the effect of jack_port_tie(). The port + * should be same as the 'destination' port passed to + * jack_port_tie(). + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_port_untie (jack_port_t *port); + +/** + * A client may call this function to prevent other objects + * from changing the connection status of a port. The port + * must be owned by the calling client. + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_port_lock (jack_client_t *, jack_port_t *); + +/** + * This allows other objects to change the connection status of a port. + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_port_unlock (jack_client_t *, jack_port_t *); + +/** + * @return the time (in frames) between data being available or + * delivered at/to a port, and the time at which it arrived at or is + * delivered to the "other side" of the port. E.g. for a physical + * audio output port, this is the time between writing to the port and + * when the signal will leave the connector. For a physical audio + * input port, this is the time between the sound arriving at the + * connector and the corresponding frames being readable from the + * port. + */ +jack_nframes_t jack_port_get_latency (jack_port_t *port); + +/** + * The maximum of the sum of the latencies in every + * connection path that can be drawn between the port and other + * ports with the @ref JackPortIsTerminal flag set. + */ +jack_nframes_t jack_port_get_total_latency (jack_client_t *, + jack_port_t *port); + +/** + * The port latency is zero by default. Clients that control + * physical hardware with non-zero latency should call this + * to set the latency to its correct value. Note that the value + * should include any systemic latency present "outside" the + * physical hardware controlled by the client. For example, + * for a client controlling a digital audio interface connected + * to an external digital converter, the latency setting should + * include both buffering by the audio interface *and* the converter. + */ +void jack_port_set_latency (jack_port_t *, jack_nframes_t); + +/** + * Modify a port's short name. May be called at any time. If the + * resulting full name (including the @a "client_name:" prefix) is + * longer than jack_port_name_size(), it will be truncated. + * + * @return 0 on success, otherwise a non-zero error code. + */ +int jack_port_set_name (jack_port_t *port, const char *port_name); + +/** + * If @ref JackPortCanMonitor is set for this @a port, turn input + * monitoring on or off. Otherwise, do nothing. + */ +int jack_port_request_monitor (jack_port_t *port, int onoff); + +/** + * If @ref JackPortCanMonitor is set for this @a port_name, turn input + * monitoring on or off. Otherwise, do nothing. + * + * @return 0 on success, otherwise a non-zero error code. + * + * @see jack_port_name_size() + */ +int jack_port_request_monitor_by_name (jack_client_t *client, + const char *port_name, int onoff); + +/** + * If @ref JackPortCanMonitor is set for a port, this function turns + * on input monitoring if it was off, and turns it off if only one + * request has been made to turn it on. Otherwise it does nothing. + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_port_ensure_monitor (jack_port_t *port, int onoff); + +/** + * @return TRUE if input monitoring has been requested for @a port. + */ +int jack_port_monitoring_input (jack_port_t *port); + +/** + * Establish a connection between two ports. + * + * When a connection exists, data written to the source port will + * be available to be read at the destination port. + * + * @pre The port types must be identical. + * + * @pre The @ref JackPortFlags of the @a source_port must include @ref + * JackPortIsOutput. + * + * @pre The @ref JackPortFlags of the @a destination_port must include + * @ref JackPortIsInput. + * + * @return 0 on success, EEXIST if the connection is already made, + * otherwise a non-zero error code + */ +int jack_connect (jack_client_t *, + const char *source_port, + const char *destination_port); + +/** + * Remove a connection between two ports. + * + * @pre The port types must be identical. + * + * @pre The @ref JackPortFlags of the @a source_port must include @ref + * JackPortIsOutput. + * + * @pre The @ref JackPortFlags of the @a destination_port must include + * @ref JackPortIsInput. + * + * @return 0 on success, otherwise a non-zero error code + */ +int jack_disconnect (jack_client_t *, + const char *source_port, + const char *destination_port); + +/** + * Perform the same function as jack_disconnect() using port handles + * rather than names. This avoids the name lookup inherent in the + * name-based version. + * + * Clients connecting their own ports are likely to use this function, + * while generic connection clients (e.g. patchbays) would use + * jack_disconnect(). + */ +int jack_port_disconnect (jack_client_t *, jack_port_t *); + +/** + * @return the maximum number of characters in a full JACK port name + * including the final NULL character. This value is a constant. + * + * A port's full name contains the owning client name concatenated + * with a colon (:) followed by its short name and a NULL + * character. + */ +int jack_port_name_size(void); + +/** + * @return the maximum number of characters in a JACK port type name + * including the final NULL character. This value is a constant. + */ +int jack_port_type_size(void); + +/** + * @return the sample rate of the jack system, as set by the user when + * jackd was started. + */ +jack_nframes_t jack_get_sample_rate (jack_client_t *); + +/** + * @return the current maximum size that will ever be passed to the @a + * process_callback. It should only be used *before* the client has + * been activated. This size may change, clients that depend on it + * must register a @a bufsize_callback so they will be notified if it + * does. + * + * @see jack_set_buffer_size_callback() + */ +jack_nframes_t jack_get_buffer_size (jack_client_t *); + +/** + * @param port_name_pattern A regular expression used to select + * ports by name. If NULL or of zero length, no selection based + * on name will be carried out. + * @param type_name_pattern A regular expression used to select + * ports by type. If NULL or of zero length, no selection based + * on type will be carried out. + * @param flags A value used to select ports by their flags. + * If zero, no selection based on flags will be carried out. + * + * @return a NULL-terminated array of ports that match the specified + * arguments. The caller is responsible for calling free(3) any + * non-NULL returned value. + * + * @see jack_port_name_size(), jack_port_type_size() + */ +const char **jack_get_ports (jack_client_t *, + const char *port_name_pattern, + const char *type_name_pattern, + unsigned long flags); + +/** + * @return address of the jack_port_t named @a port_name. + * + * @see jack_port_name_size() + */ +jack_port_t *jack_port_by_name (jack_client_t *, const char *port_name); + +/** + * @return address of the jack_port_t of a @a port_id. + */ +jack_port_t *jack_port_by_id (const jack_client_t *client, + jack_port_id_t port_id); + +/** + * Old-style interface to become the timebase for the entire JACK + * subsystem. + * + * @deprecated This function still exists for compatibility with the + * earlier transport interface, but it does nothing. Instead, see + * transport.h and use jack_set_timebase_callback(). + * + * @return ENOSYS, function not implemented. + */ +int jack_engine_takeover_timebase (jack_client_t *); + +/** + * @return the time in frames that has passed since the JACK server + * began the current process cycle. + */ +jack_nframes_t jack_frames_since_cycle_start (const jack_client_t *); + +/** + * @return an estimate of the current time in frames. This is a + * running counter, no significance should be attached to its value, + * but it can be compared to a previously returned value. + */ +jack_nframes_t jack_frame_time (const jack_client_t *); + +/** + * @return the frame_time after the last processing of the graph + * this is only to be used from the process callback. + * + * This function can be used to put timestamps generated by + * jack_frame_time() in correlation to the current process cycle. + */ +jack_nframes_t jack_last_frame_time (const jack_client_t *client); + + +/** + * @return the current CPU load estimated by JACK. This is a running + * average of the time it takes to execute a full process cycle for + * all clients as a percentage of the real time available per cycle + * determined by the buffer size and sample rate. + */ +float jack_cpu_load (jack_client_t *client); + +/** + * Set the directory in which the server is expected + * to have put its communication FIFOs. A client + * will need to call this before calling + * jack_client_new() if the server was started + * with arguments telling it to use a non-standard + * directory. + * + * @deprecated This function is deprecated. Don't use in new programs + * and remove it in old programs. + */ +void jack_set_server_dir (const char *path); + +/** + * @return the pthread ID of the thread running the JACK client side + * code. + */ +pthread_t jack_client_thread_id (jack_client_t *); + +/** + * Display JACK error message. + * + * Set via jack_set_error_function(), otherwise a JACK-provided + * default will print @a msg (plus a newline) to stderr. + * + * @param msg error message text (no newline at end). + */ +extern void (*jack_error_callback)(const char *msg); + +/** + * Set the @ref jack_error_callback for error message display. + * + * The JACK library provides two built-in callbacks for this purpose: + * default_jack_error_callback() and silent_jack_error_callback(). + */ +void jack_set_error_function (void (*func)(const char *)); +__uint64 jack_get_current_transport_frame(void* client) ; +void jack_transport_stop (void * dummy) ; +void jack_transport_start (void * dummy) ; +void jack_transport_locate (void * dummy,int x) ; +#define JACK_DEFAULT_AUDIO_TYPE 0 +#ifdef __cplusplus +} +#endif + +#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 @@ +#ifdef LINUX +#include //dave +#include //dave + +#endif + 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 @@ +#include +#include +void SmartLoader::SmartFind(const char* filename,const char* absprogpath,char* result) +{ +/* Find the given file in a clever way: + * Search the given path first + * (on the Mac, perhaps recursively) + * Then the environment PATH variable + * and finally any predefined library paths */ + result[0]=(char)0; + hd24utils::findfile(filename,absprogpath,result); + if (strlen(result)!=0) + { + // found it already + return; + } + + hd24utils::findfile(filename,getenv("PATH"),result); + if (strlen(result)!=0) + { + // found it already + return; + } + + hd24utils::findfile(filename,DEFAULTLIBPATH,result); + if (strlen(result)!=0) + { + // found it already + return; + } + return; +}; + +PortAudioWrapper::PortAudioWrapper(char* absprogpath) +{ + libloaded=false; + Pa_Initialize=NULL; + Pa_Terminate=NULL; + char result[2048]; + SmartFind(LIBFILE_PORTAUDIO,absprogpath,&result[0]); + + string abslib=""; + abslib+=result; + abslib+=LIBFILE_PORTAUDIO; + #if (RECORDERDEBUG==1) + cout << "Opening from smartpath: " << abslib.c_str() << endl; + #endif + + LIBHANDLE_T* handle=dlopen(abslib.c_str(),RTLD_NOW); + if (handle==NULL) { + #if (RECORDERDEBUG==1) + cout << "Fail. Opening from default path instead." << endl; + #endif + + handle=dlopen(LIBFILE_PORTAUDIO,RTLD_NOW); + if (handle==NULL) { + #if (RECORDERDEBUG==1) + cout << dlerror() << endl; + #endif + } else { + #if (RECORDERDEBUG==1) + cout << dlerror() << endl; + cout << "Defining functions from default path." << endl; + #endif + define_functions(handle); + + } + } else { + #if (RECORDERDEBUG==1) + cout << "Defining functions from smart path." << endl; + #endif + + define_functions(handle); + } +} + +PortAudioWrapper::~PortAudioWrapper() +{ + if (libhandle!=NULL) + { + dlclose(libhandle); + } +} + +void PortAudioWrapper::define_functions(LIBHANDLE_T* handle) +{ + if (handle==NULL) return; + libhandle=handle; + libloaded=false; + // Given a handle to a dynamic library, define functions that are in it. + + #if (RECORDERDEBUG==1) + cout << "Define Pa_Initialize..." << endl; + #endif + Pa_Initialize=(PaError (*)(void))dlsym(handle,"Pa_Initialize"); + + if (Pa_Initialize==NULL) { fl_message("Error loading Pa_Initialize"); return; } + #if (RECORDERDEBUG==1) + cout << "Define Pa_Terminate..." << endl; + #endif + + + Pa_Terminate=(PaError (*)(void))dlsym(handle,"Pa_Terminate"); + if (Pa_Terminate==NULL) { fl_message("Error loading Pa_Terminate"); return; } + + #if (RECORDERDEBUG==1) + cout << "Define Pa_StartStream..." << endl; + #endif + + Pa_StartStream=(PaError (*)(PaStream*))dlsym(handle,"Pa_StartStream"); + if (Pa_StartStream==NULL) { fl_message("Error loading Pa_StartStream"); return; } + + #if (RECORDERDEBUG==1) + cout << "Define Pa_StopStream..." << endl; + #endif + + Pa_StopStream=(PaError (*)(PaStream*))dlsym(handle,"Pa_StopStream"); + if (Pa_StopStream==NULL) { fl_message("Error loading Pa_StopStream"); return; } + + #if (RECORDERDEBUG==1) + cout << "Define Pa_AbortStream..." << endl; + #endif + + Pa_AbortStream=(PaError (*)(PaStream*))dlsym(handle,"Pa_AbortStream"); + if (Pa_AbortStream==NULL) { fl_message("Error loading Pa_AbortStream"); return; } + + #if (RECORDERDEBUG==1) + cout << "Define Pa_CloseStream..." << endl; + #endif + + Pa_CloseStream=(PaError (*)(PaStream*))dlsym(handle,"Pa_CloseStream"); + if (Pa_CloseStream==NULL) { fl_message("Error loading Pa_CloseStream"); return; } + + #if (RECORDERDEBUG==1) + cout << "Define Pa_GetStreamTime..." << endl; + #endif + + Pa_GetStreamTime=(PaTime (*)(PaStream*))dlsym(handle,"Pa_GetStreamTime"); + if (Pa_GetStreamTime==NULL) { fl_message("Error loading Pa_GetStreamTime"); return; } + + #if (RECORDERDEBUG==1) + cout << "Define Pa_StreamActive..." << endl; + #endif + + Pa_StreamActive=(PaError (*)(PaStream*))dlsym(handle,"Pa_IsStreamActive"); + if (Pa_StreamActive==NULL) { + Pa_StreamActive=(PaError (*)(PaStream*))dlsym(handle,"Pa_StreamActive"); + } + if (Pa_StreamActive==NULL) { + fl_message("Error loading Pa_StreamActive"); return; + } + + #if (RECORDERDEBUG==1) + cout << "Define Pa_OpenStream..." << endl; + #endif + Pa_OpenStream=(PaError (*)(PaStream**, + const PaStreamParameters*, + const PaStreamParameters*, + double, + unsigned long, + PaStreamFlags, + PaStreamCallback*, + void*))dlsym(handle,"Pa_OpenStream"); + + if (Pa_OpenStream==NULL) { fl_message("Error loading Pa_OpenStream"); return; } + + #if (RECORDERDEBUG==1) + cout << "Define Pa_GetDeviceCount..." << endl; + #endif + + Pa_GetDeviceCount=(int (*)(void))dlsym(handle,"Pa_GetDeviceCount"); + if (Pa_GetDeviceCount==NULL) { fl_message("Error loading Pa_GetDeviceCount"); return; } + + #if (RECORDERDEBUG==1) + cout << "Define Pa_GetDeviceInfo..." << endl; + #endif + + Pa_GetDeviceInfo=(const PaDeviceInfo* (*)(int))dlsym(handle,"Pa_GetDeviceInfo"); + if (Pa_GetDeviceInfo==NULL) { fl_message("Error loading Pa_GetDeviceInfo"); return; } + + #if (RECORDERDEBUG==1) + cout << "Define Pa_GetDefaultInputDevice..." << endl; + #endif + + Pa_GetDefaultInputDevice=(PaDeviceIndex (*)(void))dlsym(handle,"Pa_GetDefaultInputDevice"); + if (Pa_GetDefaultInputDevice==NULL) { fl_message("Error loading Pa_GetDefaultInputDevice"); return; } + + #if (RECORDERDEBUG==1) + cout << "Define Pa_GetDefaultOutputDevice..." << endl; + #endif + + Pa_GetDefaultOutputDevice=(PaDeviceIndex (*)(void))dlsym(handle,"Pa_GetDefaultOutputDevice"); + if (Pa_GetDefaultOutputDevice==NULL) { fl_message("Error loading Pa_GetDefaultOutputDevice"); return; } + + #if (RECORDERDEBUG==1) + cout << "Define Pa_GetVersionText..." << endl; + #endif + + Pa_GetVersionText=(const char* (*)(void))dlsym(handle,"Pa_GetVersionText"); + + #if (RECORDERDEBUG==1) + cout << "Define Pa_GetErrorText..." << endl; + #endif + + Pa_GetErrorText=(const char* (*)(PaError))dlsym(handle,"Pa_GetErrorText"); + + #if (RECORDERDEBUG==1) + PaError initerror=(*(this->Pa_Initialize))(); + cout << "initerror=" < +#include +#include +#include + +class SmartLoader +{ +public: + void SmartFind(const char* filename,const char* absprogpath,char* result); +}; + +class PortAudioWrapper:SmartLoader +{ +/* This class dynamically smart-loads the portaudio library, if available */ +private: + + char libloadedstring[1024]; + +public: + + PaError (*Pa_Initialize)(void); + PaError (*Pa_Terminate)(void); + PaError (*Pa_StartStream)(PaStream*); + PaError (*Pa_StopStream)(PaStream*); + PaError (*Pa_AbortStream)(PaStream*); + PaError (*Pa_CloseStream)(PaStream*); + PaError (*Pa_StreamActive)(PaStream*); + PaTime (*Pa_GetStreamTime)(PaStream*); + PaError (*Pa_OpenStream)(PaStream **stream,const PaStreamParameters *inputParameters,const PaStreamParameters *outputParameters,double sampleRate,unsigned long framesPerBuffer,PaStreamFlags streamFlags,PaStreamCallback *streamCallback,void* userData); + int (*Pa_GetDefaultInputDevice)(void); + int (*Pa_GetDefaultOutputDevice)(void); + int (*Pa_GetDeviceCount)(void); + const char* (*Pa_GetVersionText)(void); + const char* (*Pa_GetErrorText)(PaError ErrorCode); + const PaDeviceInfo* (*Pa_GetDeviceInfo)(int); + + void define_functions(LIBHANDLE_T* handle); + PortAudioWrapper(char* absprogpath); + ~PortAudioWrapper(); + int libloaded; + void* libhandle; + +}; + +class SoundFileWrapper:SmartLoader +{ +public: + /* This class dynamically smart-loads libsndfile, if available */ + SNDFILE* (*sf_open)(const char*,int,SF_INFO*); + int (*sf_close)(SNDFILE*); + sf_count_t (*sf_read_int)(SNDFILE*,int*,sf_count_t); + sf_count_t (*sf_write_raw)(SNDFILE*,const void*,sf_count_t); + sf_count_t (*sf_write_float)(SNDFILE*,const void*,sf_count_t); + void define_functions(LIBHANDLE_T* handle); + SoundFileWrapper(char* absprogpath); + ~SoundFileWrapper(); + int libloaded; + void* libhandle; +}; + +class JackWrapper:SmartLoader +{ +public: + jack_client_t* (*jack_client_new)(const char*); + int (*jack_set_process_callback)(jack_client_t*,JackProcessCallback,void*); + void (*jack_on_shutdown)(jack_client_t*,void (*function)(void *), void *); + jack_nframes_t (*jack_get_sample_rate)(jack_client_t*); + void* (*jack_port_get_buffer)(jack_port_t*,jack_nframes_t); + + jack_transport_state_t (*jack_transport_query)(const jack_client_t*,jack_position_t*); + jack_port_t* (*jack_port_register)(jack_client_t*,const char*,const char*,unsigned long,unsigned long); + int (*jack_activate)(jack_client_t*); + jack_nframes_t (*jack_get_current_transport_frame)(const jack_client_t*); + int (*jack_transport_locate)(jack_client_t*,jack_nframes_t); + void (*jack_transport_start)(jack_client_t*); + void (*jack_transport_stop)(jack_client_t*); + void define_functions(LIBHANDLE_T* handle); + JackWrapper(char* absprogpath); + ~JackWrapper(); + int libloaded; + void* libhandle; + +}; + +#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 @@ +#include "smpte.h" +#include "memutils.h" +#define SMPTE_DEBUG 0 +SMPTEgenerator::SMPTEgenerator(__uint32 p_samplerate) +{ +#if (SMPTE_DEBUG==1) + cout << "Construct SMPTE generator with samrate=" << p_samplerate << endl; +#endif +// this->lastframe=-1; + this->prevbitnum=-1; + this->prevhalfbit=-1; + this->haveframe=0; + this->prevoutval=0; + this->framerate=30; // 30 is default for HD24. + this->bitsperframe=80; + this->nondrop=1; + this->setsamplerate(p_samplerate); + this->smpteword=(short*)memutils::mymalloc("smptegenerator::smptegenerator",80,sizeof(short)); + // pre-fill sync word + for (int i=0;i<64;i++) + { + this->smpteword[i]=0; + } + this->smpteword[64]=0; + this->smpteword[65]=0; + this->smpteword[66]=1; + this->smpteword[67]=1; + this->smpteword[68]=1; + this->smpteword[69]=1; + this->smpteword[70]=1; + this->smpteword[71]=1; + this->smpteword[72]=1; + this->smpteword[73]=1; + this->smpteword[74]=1; + this->smpteword[75]=1; + this->smpteword[76]=1; + this->smpteword[77]=1; + this->smpteword[78]=0; + this->smpteword[79]=1; +} + +SMPTEgenerator::~SMPTEgenerator() +{ + if (this==NULL) + { + return; + } + if (smpteword==NULL) + { + return; + } + memutils::myfree("SMPTE",smpteword); + smpteword=NULL; +} +void SMPTEgenerator::recalcrates() +{ + + this->bitspersecond=bitsperframe*framerate; + +} + +void SMPTEgenerator::setsamplerate(__uint32 p_samplerate) +{ + this->samplerate=p_samplerate; + this->recalcrates(); + return; +} + +void SMPTEgenerator::setframerate(__uint32 p_framerate) +{ + this->framerate=p_framerate; + this->recalcrates(); +} + +void SMPTEgenerator::fillword(int hour,int minute,int second,int frame) +{ +#if (SMPTE_DEBUG==1) + cout << "fill word for " + << hour << ":" << minute << ":" << second <<"."<smpteword[0]=((frameunits ) & 1); + this->smpteword[1]=((frameunits>>1) & 1); + this->smpteword[2]=((frameunits>>2) & 1); + this->smpteword[3]=((frameunits>>3) & 1); +// this->smpteword[4]=0; +// this->smpteword[5]=0; +// this->smpteword[6]=0; +// this->smpteword[7]=0; + this->smpteword[8]=((frametens) & 1); + this->smpteword[9]=((frametens>>1) & 1); +// this->smpteword[10]=0; +// this->smpteword[11]=0; +// this->smpteword[12]=0; +// this->smpteword[13]=0; +// this->smpteword[14]=0; +// this->smpteword[15]=0; + this->smpteword[16]=((secondsunits ) & 1); + this->smpteword[17]=((secondsunits>>1) & 1); + this->smpteword[18]=((secondsunits>>2) & 1); + this->smpteword[19]=((secondsunits>>3) & 1); +// this->smpteword[20]=0; +// this->smpteword[21]=0; +// this->smpteword[22]=0; +// this->smpteword[23]=0; + this->smpteword[24]=((secondstens )&1); + this->smpteword[25]=((secondstens>>1)&1); + this->smpteword[26]=((secondstens>>2)&1); + this->smpteword[27]=0; // is biphasemark, filled in later + // but reset here to prevent its influence + +// this->smpteword[28]=0; +// this->smpteword[29]=0; +// this->smpteword[30]=0; +// this->smpteword[31]=0; + this->smpteword[32]=((minuteunits ) & 1); + this->smpteword[33]=((minuteunits>>1) & 1); + this->smpteword[34]=((minuteunits>>2) & 1); + this->smpteword[35]=((minuteunits>>3) & 1); +// this->smpteword[36]=0; +// this->smpteword[37]=0; +// this->smpteword[38]=0; +// this->smpteword[39]=0; + this->smpteword[40]=((minutetens ) & 1); + this->smpteword[41]=((minutetens>>1) & 1); + this->smpteword[42]=((minutetens>>2) & 1); +// this->smpteword[43]=0; # binary group flag bit +// this->smpteword[44]=0; +// this->smpteword[45]=0; +// this->smpteword[46]=0; +// this->smpteword[47]=0; + this->smpteword[48]=((hourunits )&1); + this->smpteword[49]=((hourunits>>1)&1); + this->smpteword[50]=((hourunits>>2)&1); + this->smpteword[51]=((hourunits>>3)&1); +// this->smpteword[52]=0; +// this->smpteword[53]=0; +// this->smpteword[54]=0; +// this->smpteword[55]=0; + this->smpteword[56]=((hourtens )&1); + this->smpteword[57]=((hourtens>>1)&1); +// this->smpteword[58]=0; // reserved, must be 0 +// this->smpteword[59]=0; // binary group flag bit +// this->smpteword[60]=0; +// this->smpteword[61]=0; +// this->smpteword[62]=0; +// this->smpteword[63]=0; + + // sync word already set in constructor + unsigned parity = 0; + for (int i=0; i<80; ++i) { + parity += this->smpteword[i]; + } + this->smpteword[27] = (parity & 1); +#if (SMPTE_DEBUG==1) + for (int i=0;i<80;i++) + { + cout << this->smpteword[i]; + } + cout << endl; +#endif + return; + +} +int SMPTEgenerator::modulate(int currbitval,int bitnum,int halfbit) +{ + if ((bitnum!=this->prevbitnum) || ((halfbit!=this->prevhalfbit) && (currbitval==1))) + { + this->prevoutval=1-(this->prevoutval); + } + this->prevbitnum=bitnum; + this->prevhalfbit=halfbit; + return this->prevoutval; +} + +int SMPTEgenerator::getbit(__uint32 insamnum) +{ + + this->samplesperbit=(int)((this->samplerate)/this->bitspersecond); + this->samplesperframe=(int)((this->samplerate)/framerate); + + __uint32 sampleinsecond=insamnum % this->samplerate; + __uint32 currentsecond=(insamnum-sampleinsecond)/(this->samplerate); + __uint32 currenthour=int(currentsecond/3600); + currentsecond-=3600*currenthour; + __uint32 currentminute=int(currentsecond/60); + currentsecond-=60*currentminute; + + __uint32 currentframe=(int)(sampleinsecond/this->samplesperframe); + __uint32 sampleinframe=sampleinsecond-(currentframe*this->samplesperframe); + __uint32 bitinframe=(int)(sampleinframe/this->samplesperbit); + __uint32 subbit=(int)(sampleinframe-(bitinframe*this->samplesperbit)); + __uint32 halfbit=(this->samplesperbit/2); + if ((bitinframe==0)&&(subbit==0)) + { + this->haveframe=0; + } + if (this->haveframe==0) + { + this->fillword(currenthour,currentminute,currentsecond,currentframe); + this->haveframe=1; + } + + if (subbitmodulate(smpteword[bitinframe],bitinframe,0); + } + return this->modulate(smpteword[bitinframe],bitinframe,1); +} + 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 @@ +#ifndef __smpte_h__ +#define __smpte_h__ + +using namespace std; +#include "config.h" +#include +#include + +class SMPTEgenerator +{ + private: + + short* smpteword; + int prevbitnum; + int prevhalfbit; + int prevoutval; + int framerate; + int nondrop; + int haveframe; // indicates if a new frame word must be generated + int samplerate; + + /* These are pre-calculated: */ + int bitsperframe; + int bitspersecond; + int samplesperbit; + int samplesperframe; + void recalcrates(); + void fillword(int hour,int min,int sec,int frame); + + void setsamplerate(__uint32 p_samplerate); + void setframerate(__uint32 p_samplerate); + + int modulate(int currbitval,int bitnum,int halfbit); + public: + SMPTEgenerator(__uint32 p_samplerate); + ~SMPTEgenerator(); + int getbit(__uint32 insamnum); + +}; + +#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 @@ +#ifdef LIBJACK +# include +# include +#else +# include "../lib/nojack.h" +#endif + +#ifdef LIBPORTAUDIO +# include "portaudio.h" +# define portaudiostreamtype PaStream +#else +# define portaudiostreamtype void +# define PaTime unsigned long +#endif + 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 @@ +#ifdef WINDOWS + #include + #define dlopen(a,b) LoadLibrary(a) + #define dlsym(a,b) GetProcAddress(a,b) + #define dlclose(a) /* CloseLibrary(a) */ + #define dlerror() "Error loading library" + #define LIBHANDLE_T HINSTANCE__ +#else + #include + #define LIBHANDLE_T void +#endif + 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 @@ +#!/bin/bash +g++ -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 @@ +using namespace std; +#include +#include +#include "portaudiotest.h" +#define PA_FRAMESPERBUF 512 +#define __uint32 unsigned long + +int HD24UserInterface::portaudio_process( + const void *inputBuffer, + void *outputBuffer, + __uint32 nframes, + const PaStreamCallbackTimeInfo* timeinfo, + PaStreamCallbackFlags, + void *userData) +{ + HD24UserInterface* mythis=(HD24UserInterface*)userData; + if (!mythis->havestreamtime) + { + mythis->streamtime=0; + mythis->timeoffset=timeinfo->currentTime; + mythis->havestreamtime=true; + } + mythis->streamtime+=nframes; + cout << ((mythis->streamtime)/48000) << " nframes=" << nframes <<" streamtime=" << timeinfo->currentTime-(mythis->timeoffset) << endl; + float sval=1; + for (int i=0;idevice=indevice; + inputParameters->channelCount=1; + inputParameters->sampleFormat=paFloat32; + inputParameters->suggestedLatency = Pa_GetDeviceInfo( inputParameters->device )->defaultLowInputLatency; + inputParameters->hostApiSpecificStreamInfo = NULL; + + cout << "Input params set" << endl; + cout << "Device=" << inputParameters->device << endl; + cout << "Channelcount=" << inputParameters->channelCount << endl; + cout << "sampleFormat=" << inputParameters->sampleFormat << endl; + cout << "suggestedlatency=" << inputParameters->suggestedLatency << endl; + cout << "================================="<device=outdevice; + outputParameters->channelCount=1; + outputParameters->sampleFormat=paFloat32; + outputParameters->suggestedLatency = Pa_GetDeviceInfo( outputParameters->device )->defaultLowOutputLatency; + outputParameters->hostApiSpecificStreamInfo = NULL; + + cout << "Output params set" << endl; + cout << "Device=" << outputParameters->device << endl; + cout << "Channelcount=" << outputParameters->channelCount << endl; + cout << "sampleFormat=" << outputParameters->sampleFormat << endl; + cout << "suggestedlatency=" << outputParameters->suggestedLatency << endl; + cout << "================================="<portaudioinit(); + ui->portaudio_transport_start(); + int blah; + cin >> blah; + +} + 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 @@ +#ifndef __portaudiotest_h__ +#define __portaudiotest_h__ +#ifndef __uint32 +#define __uint32 unsigned long +#endif +class HD24UserInterface +{ +private: + PaStream* portaudiostream; + bool m_isportaudioinitialized; + bool havestreamtime; + PaTime streamtime; + PaTime timeoffset; + static int portaudio_process + ( + const void *inputBuffer, + void *outputBuffer, + __uint32 nframes, + const PaStreamCallbackTimeInfo* timeinfo, + PaStreamCallbackFlags, + void *userData + ); + + PaStreamParameters* inputParameters; + PaStreamParameters* outputParameters; +public: + HD24UserInterface(); + bool isportaudioinitialized(); + void portaudioinit(); + void portaudio_transport_start(); +}; + +#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 @@ +using namespace std; +#include +#include +#include "portaudiotest.h" +#define PA_FRAMESPERBUF 512 +#define __uint32 unsigned long + +int HD24UserInterface::portaudio_process( + const void *inputBuffer, + void *outputBuffer, + __uint32 nframes, + const PaStreamCallbackTimeInfo* timeinfo, + PaStreamCallbackFlags, + void *userData) +{ + HD24UserInterface* mythis=(HD24UserInterface*)userData; + const PaStreamInfo* streaminfo=Pa_GetStreamInfo(mythis->portaudiostream); + double samplerate=streaminfo->sampleRate; + if (!mythis->havestreamtime) + { + mythis->streamtime=0; + mythis->havestreamtime=true; + } + mythis->streamtime+=nframes; + for (int i=0;idevice=indevice; + inputParameters->channelCount=1; + inputParameters->sampleFormat=paFloat32; + inputParameters->suggestedLatency = Pa_GetDeviceInfo( inputParameters->device )->defaultLowInputLatency; + inputParameters->hostApiSpecificStreamInfo = NULL; + + cout << "Input params set" << endl; + cout << "Device=" << inputParameters->device << endl; + cout << "Channelcount=" << inputParameters->channelCount << endl; + cout << "sampleFormat=" << inputParameters->sampleFormat << endl; + cout << "suggestedlatency=" << inputParameters->suggestedLatency << endl; + cout << "================================="<device=outdevice; + outputParameters->channelCount=1; + outputParameters->sampleFormat=paFloat32; + outputParameters->suggestedLatency = Pa_GetDeviceInfo( outputParameters->device )->defaultLowOutputLatency; + outputParameters->hostApiSpecificStreamInfo = NULL; + + cout << "Output params set" << endl; + cout << "Device=" << outputParameters->device << endl; + cout << "Channelcount=" << outputParameters->channelCount << endl; + cout << "sampleFormat=" << outputParameters->sampleFormat << endl; + cout << "suggestedlatency=" << outputParameters->suggestedLatency << endl; + cout << "================================="<portaudioinit(); + ui->portaudio_transport_start(); + int blah; + cin >> blah; + +} + 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 @@ +# Microsoft Developer Studio Project File - Name="hd24connect" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=hd24connect - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "hd24connect.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "hd24connect.mak" CFG="hd24connect - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "hd24connect - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "hd24connect - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "hd24connect - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# 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 +# 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 + +!ELSEIF "$(CFG)" == "hd24connect - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# 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 +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# 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 +# 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" + +!ENDIF + +# Begin Target + +# Name "hd24connect - Win32 Release" +# Name "hd24connect - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\src\lib\convertlib.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\lib\FL\Fl_Native_File_Chooser_WIN32.cxx +# End Source File +# Begin Source File + +SOURCE=.\src\frontend\hd24connect.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\lib\hd24devicenamegenerator.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\lib\hd24fs.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\src\lib\FL\Fl_Native_File_Chooser_WIN32.H +# End Source File +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# Begin Group "Fluid Source Files" + +# PROP Default_Filter "fl" +# Begin Source File + +SOURCE=.\src\frontend\dialog_choosedevice.fl + +!IF "$(CFG)" == "hd24connect - Win32 Release" + +!ELSEIF "$(CFG)" == "hd24connect - Win32 Debug" + +# Begin Custom Build - Running fluid on $(InputPath)... +InputDir=.\src\frontend +WkspDir=. +InputPath=.\src\frontend\dialog_choosedevice.fl +InputName=dialog_choosedevice + +BuildCmds= \ + $(WkspDir)/../fltk/fluid/fluidd -c $(InputPath) \ + mv $(InputName).cxx $(InputDir) \ + mv $(InputName).h $(InputDir) \ + + +"$(InputDir)/$(InputName).cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)/$(InputName).h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\src\frontend\dialog_fromto.fl + +!IF "$(CFG)" == "hd24connect - Win32 Release" + +!ELSEIF "$(CFG)" == "hd24connect - Win32 Debug" + +# Begin Custom Build - Running fluid on $(InputPath)... +InputDir=.\src\frontend +WkspDir=. +InputPath=.\src\frontend\dialog_fromto.fl +InputName=dialog_fromto + +BuildCmds= \ + $(WkspDir)/../fltk/fluid/fluidd -c $(InputPath) \ + mv $(InputName).cxx $(InputDir) \ + mv $(InputName).h $(InputDir) \ + + +"$(InputDir)/$(InputName).cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)/$(InputName).h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\src\frontend\dialog_rename.fl + +!IF "$(CFG)" == "hd24connect - Win32 Release" + +!ELSEIF "$(CFG)" == "hd24connect - Win32 Debug" + +# Begin Custom Build - Running fluid on $(InputPath)... +InputDir=.\src\frontend +WkspDir=. +InputPath=.\src\frontend\dialog_rename.fl +InputName=dialog_rename + +BuildCmds= \ + $(WkspDir)/../fltk/fluid/fluidd -c $(InputPath) \ + mv $(InputName).cxx $(InputDir) \ + mv $(InputName).h $(InputDir) \ + + +"$(InputDir)/$(InputName).cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)/$(InputName).h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\src\frontend\dialog_setlocate.fl + +!IF "$(CFG)" == "hd24connect - Win32 Release" + +!ELSEIF "$(CFG)" == "hd24connect - Win32 Debug" + +# Begin Custom Build - Running fluid on $(InputPath)... +InputDir=.\src\frontend +WkspDir=. +InputPath=.\src\frontend\dialog_setlocate.fl +InputName=dialog_setlocate + +BuildCmds= \ + $(WkspDir)/../fltk/fluid/fluidd -c $(InputPath) \ + mv $(InputName).cxx $(InputDir) \ + mv $(InputName).h $(InputDir) \ + + +"$(InputDir)/$(InputName).cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)/$(InputName).h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\src\frontend\ui_hd24connect.fl + +!IF "$(CFG)" == "hd24connect - Win32 Release" + +!ELSEIF "$(CFG)" == "hd24connect - Win32 Debug" + +# Begin Custom Build - Running fluid on $(InputPath)... +InputDir=.\src\frontend +WkspDir=. +InputPath=.\src\frontend\ui_hd24connect.fl +InputName=ui_hd24connect + +BuildCmds= \ + $(WkspDir)/../fltk/fluid/fluidd -c $(InputPath) \ + mv $(InputName).cxx $(InputDir) \ + mv $(InputName).h $(InputDir) \ + + +"$(InputDir)/$(InputName).cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)/$(InputName).h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ENDIF + +# End Source File +# Begin Source File + +SOURCE=.\src\frontend\ui_help_about.fl + +!IF "$(CFG)" == "hd24connect - Win32 Release" + +!ELSEIF "$(CFG)" == "hd24connect - Win32 Debug" + +# Begin Custom Build - Running fluid on $(InputPath)... +InputDir=.\src\frontend +WkspDir=. +InputPath=.\src\frontend\ui_help_about.fl +InputName=ui_help_about + +BuildCmds= \ + $(WkspDir)/../fltk/fluid/fluidd -c $(InputPath) \ + mv $(InputName).cxx $(InputDir) \ + mv $(InputName).h $(InputDir) \ + + +"$(InputDir)/$(InputName).cxx" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) + +"$(InputDir)/$(InputName).h" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)" + $(BuildCmds) +# End Custom Build + +!ENDIF + +# End Source File +# End Group +# Begin Group "Fluid Generated Source Files" + +# PROP Default_Filter "cxx" +# Begin Source File + +SOURCE=.\src\frontend\dialog_choosedevice.cxx +# End Source File +# Begin Source File + +SOURCE=.\src\frontend\dialog_fromto.cxx +# End Source File +# Begin Source File + +SOURCE=.\src\frontend\dialog_rename.cxx +# End Source File +# Begin Source File + +SOURCE=.\src\frontend\dialog_setlocate.cxx +# End Source File +# Begin Source File + +SOURCE=.\src\frontend\ui_hd24connect.cxx +# End Source File +# Begin Source File + +SOURCE=.\src\frontend\ui_help_about.cxx +# End Source File +# End Group +# End Target +# 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 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "hd24connect"=.\hd24connect.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + 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 @@ +# Microsoft Developer Studio Project File - Name="hd24hexview" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=hd24hexview - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "hd24hexview.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "hd24hexview.mak" CFG="hd24hexview - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "hd24hexview - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "hd24hexview - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "hd24hexview - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "./setup" /I "./src/lib" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# 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 +# ADD LINK32 fltk.lib /nologo /subsystem:windows /machine:I386 /libpath:"./fltk/lib" + +!ELSEIF "$(CFG)" == "hd24hexview - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# 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 +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# 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 +# ADD LINK32 fltkd.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept /libpath:"../fltk/lib" + +!ENDIF + +# Begin Target + +# Name "hd24hexview - Win32 Release" +# Name "hd24hexview - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\src\lib\convertlib.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\lib\hd24devicenamegenerator.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\lib\hd24fs.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\hd24hexview.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# 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 @@ +# Microsoft Developer Studio Project File - Name="hd24info" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=hd24info - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "hd24info.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "hd24info.mak" CFG="hd24info - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "hd24info - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "hd24info - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "hd24info - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "./setup" /I "./src/lib" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "WINDOWS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# 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 +# ADD LINK32 fltk.lib libsndfile.lib /nologo /subsystem:windows /machine:I386 /libpath:"./fltk/lib" /libpath:"./libsndfile" + +!ELSEIF "$(CFG)" == "hd24info - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# 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 +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# 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 +# ADD LINK32 fltkd.lib libsndfile.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept /libpath:"../fltk/lib" /libpath:"../libsndfile" + +!ENDIF + +# Begin Target + +# Name "hd24info - Win32 Release" +# Name "hd24info - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\src\lib\convertlib.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\lib\hd24devicenamegenerator.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\lib\hd24fs.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\hd24info.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# 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 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "hd24connect"=.\hd24connect.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "hd24hexview"=.\hd24hexview.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "hd24info"=.\hd24info.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "hd24towav"=.\hd24towav.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + 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 @@ +# Microsoft Developer Studio Project File - Name="hd24towav" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Application" 0x0101 + +CFG=hd24towav - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "hd24towav.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "hd24towav.mak" CFG="hd24towav - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "hd24towav - Win32 Release" (based on "Win32 (x86) Application") +!MESSAGE "hd24towav - Win32 Debug" (based on "Win32 (x86) Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "hd24towav - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /c +# 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 +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# 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 +# ADD LINK32 fltk.lib libsndfile.lib /nologo /subsystem:windows /machine:I386 /libpath:"./fltk/lib" /libpath:"./portaudio/lib" /libpath:"./libsndfile" + +!ELSEIF "$(CFG)" == "hd24towav - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /YX /FD /GZ /c +# 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 +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# 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 +# ADD LINK32 fltkd.lib libsndfile.lib /nologo /subsystem:windows /debug /machine:I386 /pdbtype:sept /libpath:"../fltk/lib" /libpath:"../libsndfile" + +!ENDIF + +# Begin Target + +# Name "hd24towav - Win32 Release" +# Name "hd24towav - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\src\lib\convertlib.cpp +# End Source File +# Begin Source File + +SOURCE=.\src\hd24towav.cpp +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project -- cgit v1.2.3