diff options
author | Mateusz Łukasik <mati75@linuxmint.pl> | 2016-02-05 21:48:39 +0100 |
---|---|---|
committer | Mateusz Łukasik <mati75@linuxmint.pl> | 2016-02-05 21:48:39 +0100 |
commit | 26646e3484d7d03d68003553d6c98ecddf2fa082 (patch) | |
tree | 1e80b6641ecb9b8ae702c524dc30fb423bad15fc /src | |
parent | 35d79008b7047120cc1f3fde00e7532ddc432755 (diff) |
Imported Upstream version 3.7.1
Diffstat (limited to 'src')
-rw-r--r-- | src/adplug/Makefile | 12 | ||||
-rw-r--r-- | src/adplug/adplug-xmms.cc | 48 | ||||
-rw-r--r-- | src/adplug/binio/binfile.cc | 247 | ||||
-rw-r--r-- | src/adplug/binio/binfile.h | 110 | ||||
-rw-r--r-- | src/adplug/binio/binio.cc | 298 | ||||
-rw-r--r-- | src/adplug/binio/binio.h | 137 | ||||
-rw-r--r-- | src/adplug/binio/binio_virtual.h | 51 | ||||
-rw-r--r-- | src/adplug/binio/binstr.cc | 114 | ||||
-rw-r--r-- | src/adplug/binio/binstr.h | 66 | ||||
-rw-r--r-- | src/adplug/core/a2m.cc | 769 | ||||
-rw-r--r-- | src/adplug/core/a2m.h | 87 | ||||
-rw-r--r-- | src/adplug/core/adl.cc | 1891 | ||||
-rw-r--r-- | src/adplug/core/adl.h | 4 | ||||
-rw-r--r-- | src/adplug/core/adlibemu.cc | 541 | ||||
-rw-r--r-- | src/adplug/core/adlibemu.h | 6 | ||||
-rw-r--r-- | src/adplug/core/adplug.cc | 244 | ||||
-rw-r--r-- | src/adplug/core/adplug.h | 15 | ||||
-rw-r--r-- | src/adplug/core/adtrack.cc | 170 | ||||
-rw-r--r-- | src/adplug/core/adtrack.h | 40 | ||||
-rw-r--r-- | src/adplug/core/amd.cc | 166 | ||||
-rw-r--r-- | src/adplug/core/amd.h | 38 | ||||
-rw-r--r-- | src/adplug/core/bam.cc | 317 | ||||
-rw-r--r-- | src/adplug/core/bam.h | 48 | ||||
-rw-r--r-- | src/adplug/core/binio_virtual.h | 90 | ||||
-rw-r--r-- | src/adplug/core/bmf.cc | 619 | ||||
-rw-r--r-- | src/adplug/core/bmf.h | 8 | ||||
-rw-r--r-- | src/adplug/core/cff.cc | 616 | ||||
-rw-r--r-- | src/adplug/core/cff.h | 110 | ||||
-rw-r--r-- | src/adplug/core/cmf.cc | 1179 | ||||
-rw-r--r-- | src/adplug/core/cmf.h | 130 | ||||
-rw-r--r-- | src/adplug/core/d00.cc | 606 | ||||
-rw-r--r-- | src/adplug/core/d00.h | 126 | ||||
-rw-r--r-- | src/adplug/core/database.cc | 430 | ||||
-rw-r--r-- | src/adplug/core/database.h | 61 | ||||
-rw-r--r-- | src/adplug/core/debug.cc | 2 | ||||
-rw-r--r-- | src/adplug/core/debug.h | 2 | ||||
-rw-r--r-- | src/adplug/core/dfm.cc | 148 | ||||
-rw-r--r-- | src/adplug/core/dfm.h | 42 | ||||
-rw-r--r-- | src/adplug/core/diskopl.h | 52 | ||||
-rw-r--r-- | src/adplug/core/dmo.cc | 473 | ||||
-rw-r--r-- | src/adplug/core/dmo.h | 8 | ||||
-rw-r--r-- | src/adplug/core/dro.cc | 126 | ||||
-rw-r--r-- | src/adplug/core/dro.h | 10 | ||||
-rw-r--r-- | src/adplug/core/dro2.cc | 174 | ||||
-rw-r--r-- | src/adplug/core/dro2.h | 72 | ||||
-rw-r--r-- | src/adplug/core/dtm.cc | 375 | ||||
-rw-r--r-- | src/adplug/core/dtm.h | 68 | ||||
-rw-r--r-- | src/adplug/core/emuopl.cc | 119 | ||||
-rw-r--r-- | src/adplug/core/emuopl.h | 12 | ||||
-rw-r--r-- | src/adplug/core/flash.cc | 197 | ||||
-rw-r--r-- | src/adplug/core/flash.h | 12 | ||||
-rw-r--r-- | src/adplug/core/fmc.cc | 290 | ||||
-rw-r--r-- | src/adplug/core/fmc.h | 130 | ||||
-rw-r--r-- | src/adplug/core/fmopl.cc | 2007 | ||||
-rw-r--r-- | src/adplug/core/fmopl.h | 184 | ||||
-rw-r--r-- | src/adplug/core/fprovide.cc | 46 | ||||
-rw-r--r-- | src/adplug/core/fprovide.h | 31 | ||||
-rw-r--r-- | src/adplug/core/hsc.cc | 344 | ||||
-rw-r--r-- | src/adplug/core/hsc.h | 36 | ||||
-rw-r--r-- | src/adplug/core/hsp.cc | 58 | ||||
-rw-r--r-- | src/adplug/core/hsp.h | 14 | ||||
-rw-r--r-- | src/adplug/core/hybrid.cc | 230 | ||||
-rw-r--r-- | src/adplug/core/hybrid.h | 6 | ||||
-rw-r--r-- | src/adplug/core/hyp.cc | 54 | ||||
-rw-r--r-- | src/adplug/core/hyp.h | 20 | ||||
-rw-r--r-- | src/adplug/core/imf.cc | 178 | ||||
-rw-r--r-- | src/adplug/core/imf.h | 60 | ||||
-rw-r--r-- | src/adplug/core/jbm.cc | 79 | ||||
-rw-r--r-- | src/adplug/core/jbm.h | 8 | ||||
-rw-r--r-- | src/adplug/core/kemuopl.h | 6 | ||||
-rw-r--r-- | src/adplug/core/ksm.cc | 538 | ||||
-rw-r--r-- | src/adplug/core/ksm.h | 58 | ||||
-rw-r--r-- | src/adplug/core/lds.cc | 857 | ||||
-rw-r--r-- | src/adplug/core/lds.h | 52 | ||||
-rw-r--r-- | src/adplug/core/mad.cc | 109 | ||||
-rw-r--r-- | src/adplug/core/mad.h | 28 | ||||
-rw-r--r-- | src/adplug/core/mid.cc | 1827 | ||||
-rw-r--r-- | src/adplug/core/mid.h | 10 | ||||
-rw-r--r-- | src/adplug/core/mididata.h | 10 | ||||
-rw-r--r-- | src/adplug/core/mkj.cc | 201 | ||||
-rw-r--r-- | src/adplug/core/mkj.h | 38 | ||||
-rw-r--r-- | src/adplug/core/msc.cc | 171 | ||||
-rw-r--r-- | src/adplug/core/msc.h | 113 | ||||
-rw-r--r-- | src/adplug/core/mtk.cc | 137 | ||||
-rw-r--r-- | src/adplug/core/mtk.h | 40 | ||||
-rw-r--r-- | src/adplug/core/opl.h | 18 | ||||
-rw-r--r-- | src/adplug/core/player.cc | 49 | ||||
-rw-r--r-- | src/adplug/core/player.h | 84 | ||||
-rw-r--r-- | src/adplug/core/players.cc | 18 | ||||
-rw-r--r-- | src/adplug/core/players.h | 14 | ||||
-rw-r--r-- | src/adplug/core/protrack.cc | 892 | ||||
-rw-r--r-- | src/adplug/core/psi.cc | 86 | ||||
-rw-r--r-- | src/adplug/core/psi.h | 12 | ||||
-rw-r--r-- | src/adplug/core/rad.cc | 164 | ||||
-rw-r--r-- | src/adplug/core/rad.h | 28 | ||||
-rw-r--r-- | src/adplug/core/rat.cc | 196 | ||||
-rw-r--r-- | src/adplug/core/rat.h | 20 | ||||
-rw-r--r-- | src/adplug/core/raw.cc | 91 | ||||
-rw-r--r-- | src/adplug/core/raw.h | 42 | ||||
-rw-r--r-- | src/adplug/core/rix.cc | 718 | ||||
-rw-r--r-- | src/adplug/core/rix.h | 10 | ||||
-rw-r--r-- | src/adplug/core/rol.cc | 51 | ||||
-rw-r--r-- | src/adplug/core/rol.h | 15 | ||||
-rw-r--r-- | src/adplug/core/s3m.cc | 789 | ||||
-rw-r--r-- | src/adplug/core/s3m.h | 136 | ||||
-rw-r--r-- | src/adplug/core/sa2.cc | 291 | ||||
-rw-r--r-- | src/adplug/core/sa2.h | 46 | ||||
-rw-r--r-- | src/adplug/core/silentopl.h | 10 | ||||
-rw-r--r-- | src/adplug/core/sng.cc | 86 | ||||
-rw-r--r-- | src/adplug/core/sng.h | 54 | ||||
-rw-r--r-- | src/adplug/core/temuopl.cc | 70 | ||||
-rw-r--r-- | src/adplug/core/temuopl.h | 8 | ||||
-rw-r--r-- | src/adplug/core/u6m.cc | 968 | ||||
-rw-r--r-- | src/adplug/core/u6m.h | 241 | ||||
-rw-r--r-- | src/adplug/core/xad.cc | 93 | ||||
-rw-r--r-- | src/adplug/core/xad.h | 56 | ||||
-rw-r--r-- | src/adplug/core/xsm.cc | 113 | ||||
-rw-r--r-- | src/adplug/core/xsm.h | 16 | ||||
-rw-r--r-- | src/alarm/alarm.cc | 49 | ||||
-rw-r--r-- | src/alarm/interface.cc | 131 | ||||
-rw-r--r-- | src/alarm/interface.h | 4 | ||||
-rw-r--r-- | src/albumart-qt/albumart.cc | 101 | ||||
-rw-r--r-- | src/albumart/albumart.cc | 18 | ||||
-rw-r--r-- | src/amidi-plug/Makefile | 9 | ||||
-rw-r--r-- | src/amidi-plug/amidi-plug.cc | 2 | ||||
-rw-r--r-- | src/amidi-plug/backend-fluidsynth/b-fluidsynth.cc | 10 | ||||
-rw-r--r-- | src/amidi-plug/i_backend.h | 6 | ||||
-rw-r--r-- | src/amidi-plug/i_configure-fluidsynth.cc | 36 | ||||
-rw-r--r-- | src/amidi-plug/i_configure-fluidsynth.h | 2 | ||||
-rw-r--r-- | src/amidi-plug/i_configure.cc | 8 | ||||
-rw-r--r-- | src/amidi-plug/i_fileinfo.cc | 56 | ||||
-rw-r--r-- | src/aosd/aosd.cc | 1 | ||||
-rw-r--r-- | src/aosd/aosd.h | 1 | ||||
-rw-r--r-- | src/aosd/aosd_cfg.cc | 3 | ||||
-rw-r--r-- | src/aosd/aosd_osd.cc | 14 | ||||
-rw-r--r-- | src/aosd/aosd_style.cc | 8 | ||||
-rw-r--r-- | src/aosd/aosd_trigger.cc | 19 | ||||
-rw-r--r-- | src/aosd/aosd_ui.cc | 172 | ||||
-rw-r--r-- | src/blur_scope/blur_scope.cc | 20 | ||||
-rw-r--r-- | src/cairo-spectrum/cairo-spectrum.cc | 5 | ||||
-rw-r--r-- | src/cd-menu-items/Makefile | 3 | ||||
-rw-r--r-- | src/cd-menu-items/cd-menu-items.cc | 4 | ||||
-rw-r--r-- | src/cdaudio-ng/cdaudio-ng.cc | 9 | ||||
-rw-r--r-- | src/coreaudio/coreaudio.cc | 10 | ||||
-rw-r--r-- | src/crossfade/crossfade.cc | 70 | ||||
-rw-r--r-- | src/cue/cue.cc | 132 | ||||
-rw-r--r-- | src/delete-files/delete-files.cc | 11 | ||||
-rw-r--r-- | src/ffaudio/ffaudio-core.cc | 2 | ||||
-rw-r--r-- | src/filewriter/filewriter.cc | 454 | ||||
-rw-r--r-- | src/filewriter/filewriter.h | 17 | ||||
-rw-r--r-- | src/filewriter/flac.cc | 3 | ||||
-rw-r--r-- | src/filewriter/mp3.cc | 617 | ||||
-rw-r--r-- | src/filewriter/plugins.h | 39 | ||||
-rw-r--r-- | src/filewriter/vorbis.cc | 48 | ||||
-rw-r--r-- | src/filewriter/wav.cc | 3 | ||||
-rw-r--r-- | src/flacng/metadata.cc | 57 | ||||
-rw-r--r-- | src/gio/gio.cc | 76 | ||||
-rw-r--r-- | src/gl-spectrum-qt/gl-spectrum.cc | 3 | ||||
-rw-r--r-- | src/gl-spectrum/gl-spectrum.cc | 57 | ||||
-rw-r--r-- | src/gtkui/columns.cc | 9 | ||||
-rw-r--r-- | src/gtkui/layout.cc | 39 | ||||
-rw-r--r-- | src/gtkui/menus.cc | 26 | ||||
-rw-r--r-- | src/gtkui/playlist_util.cc | 24 | ||||
-rw-r--r-- | src/gtkui/ui_gtk.cc | 176 | ||||
-rw-r--r-- | src/gtkui/ui_infoarea.cc | 111 | ||||
-rw-r--r-- | src/gtkui/ui_playlist_notebook.cc | 23 | ||||
-rw-r--r-- | src/gtkui/ui_playlist_widget.cc | 53 | ||||
-rw-r--r-- | src/gtkui/ui_statusbar.cc | 2 | ||||
-rw-r--r-- | src/hotkey/grab.cc | 2 | ||||
-rw-r--r-- | src/hotkey/gui.cc | 52 | ||||
-rw-r--r-- | src/hotkey/plugin.cc | 63 | ||||
-rw-r--r-- | src/hotkey/plugin.h | 6 | ||||
-rw-r--r-- | src/jack-ng/jack-ng.cc | 11 | ||||
-rw-r--r-- | src/ladspa/plugin.cc | 21 | ||||
-rw-r--r-- | src/lirc/lirc.cc | 3 | ||||
-rw-r--r-- | src/lyricwiki-qt/lyricwiki.cc | 230 | ||||
-rw-r--r-- | src/lyricwiki/lyricwiki.cc | 285 | ||||
-rw-r--r-- | src/m3u/m3u.cc | 35 | ||||
-rw-r--r-- | src/mixer/mixer.cc | 25 | ||||
-rw-r--r-- | src/modplug/modplugbmp.cc | 8 | ||||
-rw-r--r-- | src/modplug/modplugbmp.h | 4 | ||||
-rw-r--r-- | src/modplug/plugin_main.cc | 5 | ||||
-rw-r--r-- | src/mpg123/mpg123.cc | 350 | ||||
-rw-r--r-- | src/mpris2/plugin.cc | 53 | ||||
-rw-r--r-- | src/neon/cert_verification.cc | 70 | ||||
-rw-r--r-- | src/neon/neon.cc | 63 | ||||
-rw-r--r-- | src/notify/event.cc | 36 | ||||
-rw-r--r-- | src/notify/event.h | 4 | ||||
-rw-r--r-- | src/notify/notify.cc | 4 | ||||
-rw-r--r-- | src/notify/osd.cc | 14 | ||||
-rw-r--r-- | src/notify/osd.h | 2 | ||||
-rw-r--r-- | src/oss4/oss.cc | 20 | ||||
-rw-r--r-- | src/oss4/oss.h | 1 | ||||
-rw-r--r-- | src/oss4/plugin.cc | 3 | ||||
-rw-r--r-- | src/oss4/utils.cc | 3 | ||||
-rw-r--r-- | src/playlist-manager-qt/Makefile | 13 | ||||
-rw-r--r-- | src/playlist-manager-qt/playlist-manager-qt.cc | 336 | ||||
-rw-r--r-- | src/playlist-manager/playlist-manager.cc | 10 | ||||
-rw-r--r-- | src/psf/eng_protos.h | 3 | ||||
-rw-r--r-- | src/qtui/Makefile | 3 | ||||
-rw-r--r-- | src/qtui/dialog_windows.cc | 19 | ||||
-rw-r--r-- | src/qtui/dialog_windows.h | 3 | ||||
-rw-r--r-- | src/qtui/filter_input.cc | 2 | ||||
-rw-r--r-- | src/qtui/filter_input.h | 4 | ||||
-rw-r--r-- | src/qtui/info_bar.cc | 245 | ||||
-rw-r--r-- | src/qtui/info_bar.h | 74 | ||||
-rw-r--r-- | src/qtui/main_window.cc | 125 | ||||
-rw-r--r-- | src/qtui/main_window.h | 16 | ||||
-rw-r--r-- | src/qtui/main_window_actions.cc | 39 | ||||
-rw-r--r-- | src/qtui/playlist.cc | 98 | ||||
-rw-r--r-- | src/qtui/playlist.h | 14 | ||||
-rw-r--r-- | src/qtui/playlist_model.cc | 22 | ||||
-rw-r--r-- | src/qtui/playlist_tabs.cc | 199 | ||||
-rw-r--r-- | src/qtui/playlist_tabs.h | 38 | ||||
-rw-r--r-- | src/qtui/qtui.cc | 25 | ||||
-rw-r--r-- | src/qtui/settings.cc | 74 | ||||
-rw-r--r-- | src/qtui/settings.h | 28 | ||||
-rw-r--r-- | src/qtui/status_bar.cc | 2 | ||||
-rw-r--r-- | src/qtui/status_bar.h | 2 | ||||
-rw-r--r-- | src/qtui/time_slider.cc | 5 | ||||
-rw-r--r-- | src/qtui/time_slider.h | 7 | ||||
-rw-r--r-- | src/qtui/tool_bar.cc | 9 | ||||
-rw-r--r-- | src/qtui/tool_bar.h | 11 | ||||
-rw-r--r-- | src/scrobbler2/config_window.cc | 66 | ||||
-rw-r--r-- | src/scrobbler2/scrobbler.cc | 30 | ||||
-rw-r--r-- | src/scrobbler2/scrobbler_communication.cc | 116 | ||||
-rw-r--r-- | src/scrobbler2/scrobbler_xml_parsing.cc | 48 | ||||
-rw-r--r-- | src/search-tool-qt/Makefile | 13 | ||||
-rw-r--r-- | src/search-tool-qt/search-tool-qt.cc | 769 | ||||
-rw-r--r-- | src/search-tool/search-tool.cc | 149 | ||||
-rw-r--r-- | src/sid/xs_config.cc | 2 | ||||
-rw-r--r-- | src/sid/xs_config.h | 2 | ||||
-rw-r--r-- | src/skins-data/Makefile | 124 | ||||
-rw-r--r-- | src/skins-data/Skins/Classic/balance.png (renamed from src/skins/Skins/Classic/balance.png) | bin | 814 -> 814 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Classic/cbuttons.png (renamed from src/skins/Skins/Classic/cbuttons.png) | bin | 3987 -> 3987 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Classic/eq_ex.png (renamed from src/skins/Skins/Classic/eq_ex.png) | bin | 1566 -> 1566 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Classic/eqmain.png (renamed from src/skins/Skins/Classic/eqmain.png) | bin | 3675 -> 3675 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Classic/main.png (renamed from src/skins/Skins/Classic/main.png) | bin | 5001 -> 5001 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Classic/monoster.png (renamed from src/skins/Skins/Classic/monoster.png) | bin | 312 -> 312 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Classic/nums_ex.png (renamed from src/skins/Skins/Classic/nums_ex.png) | bin | 288 -> 288 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Classic/playpaus.png (renamed from src/skins/Skins/Classic/playpaus.png) | bin | 217 -> 217 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Classic/pledit.png (renamed from src/skins/Skins/Classic/pledit.png) | bin | 19807 -> 19807 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Classic/pledit.txt (renamed from src/skins/Skins/Classic/pledit.txt) | 0 | ||||
-rw-r--r-- | src/skins-data/Skins/Classic/posbar.png (renamed from src/skins/Skins/Classic/posbar.png) | bin | 417 -> 417 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Classic/shufrep.png (renamed from src/skins/Skins/Classic/shufrep.png) | bin | 1032 -> 1032 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Classic/skin-classic.hints (renamed from src/skins/Skins/Classic/skin-classic.hints) | 0 | ||||
-rw-r--r-- | src/skins-data/Skins/Classic/skin.hints (renamed from src/skins/Skins/Classic/skin.hints) | 0 | ||||
-rw-r--r-- | src/skins-data/Skins/Classic/text.png (renamed from src/skins/Skins/Classic/text.png) | bin | 610 -> 610 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Classic/titlebar.png (renamed from src/skins/Skins/Classic/titlebar.png) | bin | 7750 -> 7750 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Classic/viscolor.txt (renamed from src/skins/Skins/Classic/viscolor.txt) | 0 | ||||
-rw-r--r-- | src/skins-data/Skins/Classic/volume.png (renamed from src/skins/Skins/Classic/volume.png) | bin | 780 -> 780 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Classic1.3/balance.png (renamed from src/skins/Skins/Classic1.3/balance.png) | bin | 1457 -> 1457 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Classic1.3/cbuttons.png (renamed from src/skins/Skins/Classic1.3/cbuttons.png) | bin | 4291 -> 4291 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Classic1.3/eq_ex.png (renamed from src/skins/Skins/Classic1.3/eq_ex.png) | bin | 1566 -> 1566 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Classic1.3/eqmain.png (renamed from src/skins/Skins/Classic1.3/eqmain.png) | bin | 3675 -> 3675 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Classic1.3/main.png (renamed from src/skins/Skins/Classic1.3/main.png) | bin | 1889 -> 1889 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Classic1.3/monoster.png (renamed from src/skins/Skins/Classic1.3/monoster.png) | bin | 312 -> 312 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Classic1.3/nums_ex.png (renamed from src/skins/Skins/Classic1.3/nums_ex.png) | bin | 288 -> 288 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Classic1.3/playpaus.png (renamed from src/skins/Skins/Classic1.3/playpaus.png) | bin | 217 -> 217 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Classic1.3/pledit.png (renamed from src/skins/Skins/Classic1.3/pledit.png) | bin | 19807 -> 19807 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Classic1.3/pledit.txt (renamed from src/skins/Skins/Classic1.3/pledit.txt) | 0 | ||||
-rw-r--r-- | src/skins-data/Skins/Classic1.3/posbar.png (renamed from src/skins/Skins/Classic1.3/posbar.png) | bin | 541 -> 541 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Classic1.3/shufrep.png (renamed from src/skins/Skins/Classic1.3/shufrep.png) | bin | 2365 -> 2365 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Classic1.3/skin-classic.hints (renamed from src/skins/Skins/Classic1.3/skin-classic.hints) | 0 | ||||
-rw-r--r-- | src/skins-data/Skins/Classic1.3/skin.hints (renamed from src/skins/Skins/Classic1.3/skin.hints) | 0 | ||||
-rw-r--r-- | src/skins-data/Skins/Classic1.3/text.png (renamed from src/skins/Skins/Classic1.3/text.png) | bin | 610 -> 610 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Classic1.3/titlebar.png (renamed from src/skins/Skins/Classic1.3/titlebar.png) | bin | 6233 -> 6233 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Classic1.3/viscolor.txt (renamed from src/skins/Skins/Classic1.3/viscolor.txt) | 0 | ||||
-rw-r--r-- | src/skins-data/Skins/Classic1.3/volume.png (renamed from src/skins/Skins/Classic1.3/volume.png) | bin | 1627 -> 1627 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/balance.png (renamed from src/skins/Skins/Default/balance.png) | bin | 1457 -> 1457 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/cbuttons.png (renamed from src/skins/Skins/Default/cbuttons.png) | bin | 2937 -> 2937 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/eq_ex.png (renamed from src/skins/Skins/Default/eq_ex.png) | bin | 2198 -> 2198 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/eqmain.png (renamed from src/skins/Skins/Default/eqmain.png) | bin | 5982 -> 5982 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Arrows/arrow-down.png (renamed from src/skins/Skins/Default/gtk-2.0/Arrows/arrow-down.png) | bin | 163 -> 163 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Arrows/arrow-insens.png (renamed from src/skins/Skins/Default/gtk-2.0/Arrows/arrow-insens.png) | bin | 190 -> 190 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Arrows/arrow-left.png (renamed from src/skins/Skins/Default/gtk-2.0/Arrows/arrow-left.png) | bin | 165 -> 165 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Arrows/arrow-right.png (renamed from src/skins/Skins/Default/gtk-2.0/Arrows/arrow-right.png) | bin | 170 -> 170 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Arrows/arrow-up.png (renamed from src/skins/Skins/Default/gtk-2.0/Arrows/arrow-up.png) | bin | 188 -> 188 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Buttons/button-insensitive.png (renamed from src/skins/Skins/Default/gtk-2.0/Buttons/button-insensitive.png) | bin | 237 -> 237 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Buttons/button-normal.png (renamed from src/skins/Skins/Default/gtk-2.0/Buttons/button-normal.png) | bin | 237 -> 237 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Buttons/button-prelight.png (renamed from src/skins/Skins/Default/gtk-2.0/Buttons/button-prelight.png) | bin | 611 -> 611 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Check-Radio/check1.png (renamed from src/skins/Skins/Default/gtk-2.0/Check-Radio/check1.png) | bin | 147 -> 147 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Check-Radio/check2.png (renamed from src/skins/Skins/Default/gtk-2.0/Check-Radio/check2.png) | bin | 214 -> 214 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Check-Radio/check3.png (renamed from src/skins/Skins/Default/gtk-2.0/Check-Radio/check3.png) | bin | 180 -> 180 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Check-Radio/check4.png (renamed from src/skins/Skins/Default/gtk-2.0/Check-Radio/check4.png) | bin | 300 -> 300 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Check-Radio/check5.png (renamed from src/skins/Skins/Default/gtk-2.0/Check-Radio/check5.png) | bin | 150 -> 150 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Check-Radio/check6.png (renamed from src/skins/Skins/Default/gtk-2.0/Check-Radio/check6.png) | bin | 226 -> 226 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Check-Radio/option1.png (renamed from src/skins/Skins/Default/gtk-2.0/Check-Radio/option1.png) | bin | 249 -> 249 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Check-Radio/option2.png (renamed from src/skins/Skins/Default/gtk-2.0/Check-Radio/option2.png) | bin | 278 -> 278 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Check-Radio/option3.png (renamed from src/skins/Skins/Default/gtk-2.0/Check-Radio/option3.png) | bin | 333 -> 333 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Check-Radio/option4.png (renamed from src/skins/Skins/Default/gtk-2.0/Check-Radio/option4.png) | bin | 330 -> 330 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Check-Radio/option5.png (renamed from src/skins/Skins/Default/gtk-2.0/Check-Radio/option5.png) | bin | 246 -> 246 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Check-Radio/option6.png (renamed from src/skins/Skins/Default/gtk-2.0/Check-Radio/option6.png) | bin | 273 -> 273 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Frame-Gap/frame-gap-end.png (renamed from src/skins/Skins/Default/gtk-2.0/Frame-Gap/frame-gap-end.png) | bin | 131 -> 131 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Frame-Gap/frame-gap-start.png (renamed from src/skins/Skins/Default/gtk-2.0/Frame-Gap/frame-gap-start.png) | bin | 131 -> 131 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Frame-Gap/frame.png (renamed from src/skins/Skins/Default/gtk-2.0/Frame-Gap/frame.png) | bin | 152 -> 152 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Handles/handle-h.png (renamed from src/skins/Skins/Default/gtk-2.0/Handles/handle-h.png) | bin | 141 -> 141 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Handles/handle-v.png (renamed from src/skins/Skins/Default/gtk-2.0/Handles/handle-v.png) | bin | 137 -> 137 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Lines/line-h.png (renamed from src/skins/Skins/Default/gtk-2.0/Lines/line-h.png) | bin | 142 -> 142 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Lines/line-v.png (renamed from src/skins/Skins/Default/gtk-2.0/Lines/line-v.png) | bin | 142 -> 142 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/ListHeaders/list_header-insens.png (renamed from src/skins/Skins/Default/gtk-2.0/ListHeaders/list_header-insens.png) | bin | 182 -> 182 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/ListHeaders/list_header-prelight.png (renamed from src/skins/Skins/Default/gtk-2.0/ListHeaders/list_header-prelight.png) | bin | 428 -> 428 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/ListHeaders/list_header-pressed.png (renamed from src/skins/Skins/Default/gtk-2.0/ListHeaders/list_header-pressed.png) | bin | 129 -> 129 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/ListHeaders/list_header.png (renamed from src/skins/Skins/Default/gtk-2.0/ListHeaders/list_header.png) | bin | 165 -> 165 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Menu-Menubar/menu.png (renamed from src/skins/Skins/Default/gtk-2.0/Menu-Menubar/menu.png) | bin | 222 -> 222 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Menu-Menubar/menubar-item-active.png (renamed from src/skins/Skins/Default/gtk-2.0/Menu-Menubar/menubar-item-active.png) | bin | 661 -> 661 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Menu-Menubar/menubar-item.png (renamed from src/skins/Skins/Default/gtk-2.0/Menu-Menubar/menubar-item.png) | bin | 260 -> 260 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Menu-Menubar/menubar.png (renamed from src/skins/Skins/Default/gtk-2.0/Menu-Menubar/menubar.png) | bin | 196 -> 196 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Others/null.png (renamed from src/skins/Skins/Default/gtk-2.0/Others/null.png) | bin | 332 -> 332 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Others/ruler.png (renamed from src/skins/Skins/Default/gtk-2.0/Others/ruler.png) | bin | 131 -> 131 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Panel/panel-bg.png (renamed from src/skins/Skins/Default/gtk-2.0/Panel/panel-bg.png) | bin | 156 -> 156 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/ProgressBar/progressbar-horiz.png (renamed from src/skins/Skins/Default/gtk-2.0/ProgressBar/progressbar-horiz.png) | bin | 212 -> 212 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/ProgressBar/trough-progressbar-horiz.png (renamed from src/skins/Skins/Default/gtk-2.0/ProgressBar/trough-progressbar-horiz.png) | bin | 139 -> 139 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Range/slider-horiz-prelight.png (renamed from src/skins/Skins/Default/gtk-2.0/Range/slider-horiz-prelight.png) | bin | 429 -> 429 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Range/slider-horiz.png (renamed from src/skins/Skins/Default/gtk-2.0/Range/slider-horiz.png) | bin | 246 -> 246 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Range/slider-vert-prelight.png (renamed from src/skins/Skins/Default/gtk-2.0/Range/slider-vert-prelight.png) | bin | 420 -> 420 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Range/slider-vert.png (renamed from src/skins/Skins/Default/gtk-2.0/Range/slider-vert.png) | bin | 190 -> 190 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Range/trough-horizontal.png (renamed from src/skins/Skins/Default/gtk-2.0/Range/trough-horizontal.png) | bin | 168 -> 168 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Range/trough-vertical.png (renamed from src/skins/Skins/Default/gtk-2.0/Range/trough-vertical.png) | bin | 188 -> 188 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Scrollbars/scroll-thumb-horiz-pre.png (renamed from src/skins/Skins/Default/gtk-2.0/Scrollbars/scroll-thumb-horiz-pre.png) | bin | 172 -> 172 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Scrollbars/scroll-thumb-horiz.png (renamed from src/skins/Skins/Default/gtk-2.0/Scrollbars/scroll-thumb-horiz.png) | bin | 155 -> 155 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Scrollbars/scroll-thumb-vert-pre.png (renamed from src/skins/Skins/Default/gtk-2.0/Scrollbars/scroll-thumb-vert-pre.png) | bin | 162 -> 162 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Scrollbars/scroll-thumb-vert.png (renamed from src/skins/Skins/Default/gtk-2.0/Scrollbars/scroll-thumb-vert.png) | bin | 145 -> 145 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Scrollbars/slider-horiz-pre.png (renamed from src/skins/Skins/Default/gtk-2.0/Scrollbars/slider-horiz-pre.png) | bin | 231 -> 231 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Scrollbars/slider-horiz.png (renamed from src/skins/Skins/Default/gtk-2.0/Scrollbars/slider-horiz.png) | bin | 182 -> 182 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Scrollbars/slider-vert-pre.png (renamed from src/skins/Skins/Default/gtk-2.0/Scrollbars/slider-vert-pre.png) | bin | 214 -> 214 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Scrollbars/slider-vert.png (renamed from src/skins/Skins/Default/gtk-2.0/Scrollbars/slider-vert.png) | bin | 200 -> 200 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Scrollbars/stepper-down-prelight.png (renamed from src/skins/Skins/Default/gtk-2.0/Scrollbars/stepper-down-prelight.png) | bin | 450 -> 450 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Scrollbars/stepper-down.png (renamed from src/skins/Skins/Default/gtk-2.0/Scrollbars/stepper-down.png) | bin | 228 -> 228 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Scrollbars/stepper-left-prelight.png (renamed from src/skins/Skins/Default/gtk-2.0/Scrollbars/stepper-left-prelight.png) | bin | 469 -> 469 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Scrollbars/stepper-left.png (renamed from src/skins/Skins/Default/gtk-2.0/Scrollbars/stepper-left.png) | bin | 242 -> 242 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Scrollbars/stepper-right-prelight.png (renamed from src/skins/Skins/Default/gtk-2.0/Scrollbars/stepper-right-prelight.png) | bin | 462 -> 462 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Scrollbars/stepper-right.png (renamed from src/skins/Skins/Default/gtk-2.0/Scrollbars/stepper-right.png) | bin | 246 -> 246 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Scrollbars/stepper-up-prelight.png (renamed from src/skins/Skins/Default/gtk-2.0/Scrollbars/stepper-up-prelight.png) | bin | 474 -> 474 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Scrollbars/stepper-up.png (renamed from src/skins/Skins/Default/gtk-2.0/Scrollbars/stepper-up.png) | bin | 236 -> 236 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Scrollbars/trough-scrollbar-horiz.png (renamed from src/skins/Skins/Default/gtk-2.0/Scrollbars/trough-scrollbar-horiz.png) | bin | 342 -> 342 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Scrollbars/trough-scrollbar-vert.png (renamed from src/skins/Skins/Default/gtk-2.0/Scrollbars/trough-scrollbar-vert.png) | bin | 325 -> 325 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Shadows/shadow-in.png (renamed from src/skins/Skins/Default/gtk-2.0/Shadows/shadow-in.png) | bin | 151 -> 151 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Shadows/shadow-out.png (renamed from src/skins/Skins/Default/gtk-2.0/Shadows/shadow-out.png) | bin | 151 -> 151 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Shadows/text-.png (renamed from src/skins/Skins/Default/gtk-2.0/Shadows/text-.png) | bin | 136 -> 136 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Shadows/text-entry.png (renamed from src/skins/Skins/Default/gtk-2.0/Shadows/text-entry.png) | bin | 136 -> 136 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Spin/spin-down-disable.png (renamed from src/skins/Skins/Default/gtk-2.0/Spin/spin-down-disable.png) | bin | 226 -> 226 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Spin/spin-down-prelight.png (renamed from src/skins/Skins/Default/gtk-2.0/Spin/spin-down-prelight.png) | bin | 334 -> 334 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Spin/spin-down.png (renamed from src/skins/Skins/Default/gtk-2.0/Spin/spin-down.png) | bin | 231 -> 231 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Spin/spin-up-disable.png (renamed from src/skins/Skins/Default/gtk-2.0/Spin/spin-up-disable.png) | bin | 232 -> 232 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Spin/spin-up-prelight.png (renamed from src/skins/Skins/Default/gtk-2.0/Spin/spin-up-prelight.png) | bin | 353 -> 353 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Spin/spin-up.png (renamed from src/skins/Skins/Default/gtk-2.0/Spin/spin-up.png) | bin | 224 -> 224 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Tabs/gap-bottom-left.png (renamed from src/skins/Skins/Default/gtk-2.0/Tabs/gap-bottom-left.png) | bin | 188 -> 188 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Tabs/gap-bottom-right.png (renamed from src/skins/Skins/Default/gtk-2.0/Tabs/gap-bottom-right.png) | bin | 188 -> 188 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Tabs/gap-left-bottom.png (renamed from src/skins/Skins/Default/gtk-2.0/Tabs/gap-left-bottom.png) | bin | 188 -> 188 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Tabs/gap-left-top.png (renamed from src/skins/Skins/Default/gtk-2.0/Tabs/gap-left-top.png) | bin | 188 -> 188 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Tabs/gap-right-bottom.png (renamed from src/skins/Skins/Default/gtk-2.0/Tabs/gap-right-bottom.png) | bin | 188 -> 188 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Tabs/gap-right-top.png (renamed from src/skins/Skins/Default/gtk-2.0/Tabs/gap-right-top.png) | bin | 187 -> 187 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Tabs/gap-top-current.png (renamed from src/skins/Skins/Default/gtk-2.0/Tabs/gap-top-current.png) | bin | 199 -> 199 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Tabs/gap-top-left.png (renamed from src/skins/Skins/Default/gtk-2.0/Tabs/gap-top-left.png) | bin | 189 -> 189 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Tabs/gap-top-right.png (renamed from src/skins/Skins/Default/gtk-2.0/Tabs/gap-top-right.png) | bin | 190 -> 190 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Tabs/notebook.png (renamed from src/skins/Skins/Default/gtk-2.0/Tabs/notebook.png) | bin | 155 -> 155 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Tabs/tab-bottom-active.png (renamed from src/skins/Skins/Default/gtk-2.0/Tabs/tab-bottom-active.png) | bin | 235 -> 235 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Tabs/tab-bottom.png (renamed from src/skins/Skins/Default/gtk-2.0/Tabs/tab-bottom.png) | bin | 222 -> 222 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Tabs/tab-left-active.png (renamed from src/skins/Skins/Default/gtk-2.0/Tabs/tab-left-active.png) | bin | 240 -> 240 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Tabs/tab-left.png (renamed from src/skins/Skins/Default/gtk-2.0/Tabs/tab-left.png) | bin | 216 -> 216 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Tabs/tab-right-active.png (renamed from src/skins/Skins/Default/gtk-2.0/Tabs/tab-right-active.png) | bin | 236 -> 236 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Tabs/tab-right.png (renamed from src/skins/Skins/Default/gtk-2.0/Tabs/tab-right.png) | bin | 221 -> 221 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Tabs/tab-top-active.png (renamed from src/skins/Skins/Default/gtk-2.0/Tabs/tab-top-active.png) | bin | 230 -> 230 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Tabs/tab-top.png (renamed from src/skins/Skins/Default/gtk-2.0/Tabs/tab-top.png) | bin | 240 -> 240 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/Toolbar/toolbar.png (renamed from src/skins/Skins/Default/gtk-2.0/Toolbar/toolbar.png) | bin | 134 -> 134 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/gtkrc (renamed from src/skins/Skins/Default/gtk-2.0/gtkrc) | 0 | ||||
-rw-r--r-- | src/skins-data/Skins/Default/gtk-2.0/panel.rc (renamed from src/skins/Skins/Default/gtk-2.0/panel.rc) | 0 | ||||
-rw-r--r-- | src/skins-data/Skins/Default/main.png (renamed from src/skins/Skins/Default/main.png) | bin | 1419 -> 1419 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/monoster.png (renamed from src/skins/Skins/Default/monoster.png) | bin | 1372 -> 1372 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/nums_ex.png (renamed from src/skins/Skins/Default/nums_ex.png) | bin | 762 -> 762 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/playpaus.png (renamed from src/skins/Skins/Default/playpaus.png) | bin | 444 -> 444 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/pledit.png (renamed from src/skins/Skins/Default/pledit.png) | bin | 15074 -> 15074 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/pledit.txt (renamed from src/skins/Skins/Default/pledit.txt) | 0 | ||||
-rw-r--r-- | src/skins-data/Skins/Default/posbar.png (renamed from src/skins/Skins/Default/posbar.png) | bin | 346 -> 346 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/shufrep.png (renamed from src/skins/Skins/Default/shufrep.png) | bin | 3044 -> 3044 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/skin-classic.hints (renamed from src/skins/Skins/Default/skin-classic.hints) | 0 | ||||
-rw-r--r-- | src/skins-data/Skins/Default/skin.hints (renamed from src/skins/Skins/Default/skin.hints) | 0 | ||||
-rw-r--r-- | src/skins-data/Skins/Default/text.png (renamed from src/skins/Skins/Default/text.png) | bin | 898 -> 898 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/titlebar.png (renamed from src/skins/Skins/Default/titlebar.png) | bin | 4702 -> 4702 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Default/viscolor.txt (renamed from src/skins/Skins/Default/viscolor.txt) | 0 | ||||
-rw-r--r-- | src/skins-data/Skins/Default/volume.png (renamed from src/skins/Skins/Default/volume.png) | bin | 624 -> 624 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Ivory/balance.png (renamed from src/skins/Skins/Ivory/balance.png) | bin | 745 -> 745 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Ivory/cbuttons.png (renamed from src/skins/Skins/Ivory/cbuttons.png) | bin | 2352 -> 2352 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Ivory/eq_ex.png (renamed from src/skins/Skins/Ivory/eq_ex.png) | bin | 1089 -> 1089 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Ivory/eqmain.png (renamed from src/skins/Skins/Ivory/eqmain.png) | bin | 2783 -> 2783 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Ivory/main.png (renamed from src/skins/Skins/Ivory/main.png) | bin | 431 -> 431 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Ivory/monoster.png (renamed from src/skins/Skins/Ivory/monoster.png) | bin | 262 -> 262 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Ivory/nums_ex.png (renamed from src/skins/Skins/Ivory/nums_ex.png) | bin | 243 -> 243 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Ivory/playpaus.png (renamed from src/skins/Skins/Ivory/playpaus.png) | bin | 163 -> 163 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Ivory/pledit.png (renamed from src/skins/Skins/Ivory/pledit.png) | bin | 2090 -> 2090 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Ivory/pledit.txt (renamed from src/skins/Skins/Ivory/pledit.txt) | 0 | ||||
-rw-r--r-- | src/skins-data/Skins/Ivory/posbar.png (renamed from src/skins/Skins/Ivory/posbar.png) | bin | 320 -> 320 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Ivory/shufrep.png (renamed from src/skins/Skins/Ivory/shufrep.png) | bin | 890 -> 890 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Ivory/skin.hints (renamed from src/skins/Skins/Ivory/skin.hints) | 0 | ||||
-rw-r--r-- | src/skins-data/Skins/Ivory/text.png (renamed from src/skins/Skins/Ivory/text.png) | bin | 574 -> 574 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Ivory/titlebar.png (renamed from src/skins/Skins/Ivory/titlebar.png) | bin | 7704 -> 7704 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Ivory/viscolor.txt (renamed from src/skins/Skins/Ivory/viscolor.txt) | 0 | ||||
-rw-r--r-- | src/skins-data/Skins/Ivory/volume.png (renamed from src/skins/Skins/Ivory/volume.png) | bin | 717 -> 717 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Osmosis/balance.png (renamed from src/skins/Skins/Osmosis/balance.png) | bin | 785 -> 785 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Osmosis/cbuttons.png (renamed from src/skins/Skins/Osmosis/cbuttons.png) | bin | 2415 -> 2415 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Osmosis/eq_ex.png (renamed from src/skins/Skins/Osmosis/eq_ex.png) | bin | 1140 -> 1140 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Osmosis/eqmain.png (renamed from src/skins/Skins/Osmosis/eqmain.png) | bin | 2850 -> 2850 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Osmosis/main.png (renamed from src/skins/Skins/Osmosis/main.png) | bin | 487 -> 487 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Osmosis/monoster.png (renamed from src/skins/Skins/Osmosis/monoster.png) | bin | 312 -> 312 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Osmosis/nums_ex.png (renamed from src/skins/Skins/Osmosis/nums_ex.png) | bin | 288 -> 288 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Osmosis/playpaus.png (renamed from src/skins/Skins/Osmosis/playpaus.png) | bin | 217 -> 217 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Osmosis/pledit.png (renamed from src/skins/Skins/Osmosis/pledit.png) | bin | 2148 -> 2148 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Osmosis/pledit.txt (renamed from src/skins/Skins/Osmosis/pledit.txt) | 0 | ||||
-rw-r--r-- | src/skins-data/Skins/Osmosis/posbar.png (renamed from src/skins/Skins/Osmosis/posbar.png) | bin | 362 -> 362 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Osmosis/shufrep.png (renamed from src/skins/Skins/Osmosis/shufrep.png) | bin | 930 -> 930 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Osmosis/skin.hints (renamed from src/skins/Skins/Osmosis/skin.hints) | 0 | ||||
-rw-r--r-- | src/skins-data/Skins/Osmosis/text.png (renamed from src/skins/Skins/Osmosis/text.png) | bin | 610 -> 610 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Osmosis/titlebar.png (renamed from src/skins/Skins/Osmosis/titlebar.png) | bin | 7625 -> 7625 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Osmosis/viscolor.txt (renamed from src/skins/Skins/Osmosis/viscolor.txt) | 0 | ||||
-rw-r--r-- | src/skins-data/Skins/Osmosis/volume.png (renamed from src/skins/Skins/Osmosis/volume.png) | bin | 758 -> 758 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Refugee/cbuttons.png (renamed from src/skins/Skins/Refugee/cbuttons.png) | bin | 5032 -> 5032 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Refugee/eq_ex.png (renamed from src/skins/Skins/Refugee/eq_ex.png) | bin | 7580 -> 7580 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Refugee/eqmain.png (renamed from src/skins/Skins/Refugee/eqmain.png) | bin | 15218 -> 15218 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Refugee/main.png (renamed from src/skins/Skins/Refugee/main.png) | bin | 11342 -> 11342 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Refugee/monoster.png (renamed from src/skins/Skins/Refugee/monoster.png) | bin | 1372 -> 1372 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Refugee/numbers.png (renamed from src/skins/Skins/Refugee/numbers.png) | bin | 1150 -> 1150 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Refugee/nums_ex.png (renamed from src/skins/Skins/Refugee/nums_ex.png) | bin | 1258 -> 1258 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Refugee/playpaus.png (renamed from src/skins/Skins/Refugee/playpaus.png) | bin | 682 -> 682 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Refugee/pledit.png (renamed from src/skins/Skins/Refugee/pledit.png) | bin | 24756 -> 24756 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Refugee/pledit.txt (renamed from src/skins/Skins/Refugee/pledit.txt) | 0 | ||||
-rw-r--r-- | src/skins-data/Skins/Refugee/posbar.png (renamed from src/skins/Skins/Refugee/posbar.png) | bin | 2061 -> 2061 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Refugee/shufrep.png (renamed from src/skins/Skins/Refugee/shufrep.png) | bin | 6413 -> 6413 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Refugee/skin.hints (renamed from src/skins/Skins/Refugee/skin.hints) | 0 | ||||
-rw-r--r-- | src/skins-data/Skins/Refugee/text.png (renamed from src/skins/Skins/Refugee/text.png) | bin | 1262 -> 1262 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Refugee/titlebar.png (renamed from src/skins/Skins/Refugee/titlebar.png) | bin | 10919 -> 10919 bytes | |||
-rw-r--r-- | src/skins-data/Skins/Refugee/viscolor.txt (renamed from src/skins/Skins/Refugee/viscolor.txt) | 0 | ||||
-rw-r--r-- | src/skins-data/Skins/Refugee/volume.png (renamed from src/skins/Skins/Refugee/volume.png) | bin | 3327 -> 3327 bytes | |||
-rw-r--r-- | src/skins-data/Skins/TinyPlayer/balance.png (renamed from src/skins/Skins/TinyPlayer/balance.png) | bin | 814 -> 814 bytes | |||
-rw-r--r-- | src/skins-data/Skins/TinyPlayer/cbuttons.png (renamed from src/skins/Skins/TinyPlayer/cbuttons.png) | bin | 3987 -> 3987 bytes | |||
-rw-r--r-- | src/skins-data/Skins/TinyPlayer/eq_ex.png (renamed from src/skins/Skins/TinyPlayer/eq_ex.png) | bin | 1566 -> 1566 bytes | |||
-rw-r--r-- | src/skins-data/Skins/TinyPlayer/eqmain.png (renamed from src/skins/Skins/TinyPlayer/eqmain.png) | bin | 3675 -> 3675 bytes | |||
-rw-r--r-- | src/skins-data/Skins/TinyPlayer/main.png (renamed from src/skins/Skins/TinyPlayer/main.png) | bin | 4601 -> 4601 bytes | |||
-rw-r--r-- | src/skins-data/Skins/TinyPlayer/monoster.png (renamed from src/skins/Skins/TinyPlayer/monoster.png) | bin | 312 -> 312 bytes | |||
-rw-r--r-- | src/skins-data/Skins/TinyPlayer/nums_ex.png (renamed from src/skins/Skins/TinyPlayer/nums_ex.png) | bin | 288 -> 288 bytes | |||
-rw-r--r-- | src/skins-data/Skins/TinyPlayer/playpaus.png (renamed from src/skins/Skins/TinyPlayer/playpaus.png) | bin | 217 -> 217 bytes | |||
-rw-r--r-- | src/skins-data/Skins/TinyPlayer/pledit.png (renamed from src/skins/Skins/TinyPlayer/pledit.png) | bin | 19807 -> 19807 bytes | |||
-rw-r--r-- | src/skins-data/Skins/TinyPlayer/pledit.txt (renamed from src/skins/Skins/TinyPlayer/pledit.txt) | 0 | ||||
-rw-r--r-- | src/skins-data/Skins/TinyPlayer/posbar.png (renamed from src/skins/Skins/TinyPlayer/posbar.png) | bin | 417 -> 417 bytes | |||
-rw-r--r-- | src/skins-data/Skins/TinyPlayer/shufrep.png (renamed from src/skins/Skins/TinyPlayer/shufrep.png) | bin | 1032 -> 1032 bytes | |||
-rw-r--r-- | src/skins-data/Skins/TinyPlayer/skin.hints (renamed from src/skins/Skins/TinyPlayer/skin.hints) | 0 | ||||
-rw-r--r-- | src/skins-data/Skins/TinyPlayer/text.png (renamed from src/skins/Skins/TinyPlayer/text.png) | bin | 610 -> 610 bytes | |||
-rw-r--r-- | src/skins-data/Skins/TinyPlayer/titlebar.png (renamed from src/skins/Skins/TinyPlayer/titlebar.png) | bin | 7750 -> 7750 bytes | |||
-rw-r--r-- | src/skins-data/Skins/TinyPlayer/viscolor.txt (renamed from src/skins/Skins/TinyPlayer/viscolor.txt) | 0 | ||||
-rw-r--r-- | src/skins-data/Skins/TinyPlayer/volume.png (renamed from src/skins/Skins/TinyPlayer/volume.png) | bin | 780 -> 780 bytes | |||
-rw-r--r-- | src/skins-qt/Makefile | 44 | ||||
-rw-r--r-- | src/skins-qt/actions-mainwin.h | 31 | ||||
-rw-r--r-- | src/skins-qt/actions-playlist.h | 83 | ||||
-rw-r--r-- | src/skins-qt/actions.cc | 295 | ||||
-rw-r--r-- | src/skins-qt/button.cc | 132 | ||||
-rw-r--r-- | src/skins-qt/button.h | 78 | ||||
-rw-r--r-- | src/skins-qt/dnd.h | 56 | ||||
-rw-r--r-- | src/skins-qt/dock.cc (renamed from src/skins/ui_dock.cc) | 246 | ||||
-rw-r--r-- | src/skins-qt/drag-handle.cc | 66 | ||||
-rw-r--r-- | src/skins-qt/drag-handle.h (renamed from src/skins/ui_dock.h) | 28 | ||||
-rw-r--r-- | src/skins-qt/eq-graph.cc | 135 | ||||
-rw-r--r-- | src/skins-qt/eq-graph.h (renamed from src/skins/ui_skinned_playlist_slider.h) | 18 | ||||
-rw-r--r-- | src/skins-qt/eq-slider.cc | 124 | ||||
-rw-r--r-- | src/skins-qt/eq-slider.h (renamed from src/skins/ui_skinned_equalizer_slider.h) | 29 | ||||
-rw-r--r-- | src/skins-qt/equalizer.cc | 285 | ||||
-rw-r--r-- | src/skins-qt/equalizer.h (renamed from src/skins/ui_equalizer.h) | 28 | ||||
-rw-r--r-- | src/skins-qt/hslider.cc | 129 | ||||
-rw-r--r-- | src/skins-qt/hslider.h | 70 | ||||
-rw-r--r-- | src/skins-qt/main.cc | 1185 | ||||
-rw-r--r-- | src/skins-qt/main.h (renamed from src/skins/ui_main.h) | 68 | ||||
-rw-r--r-- | src/skins-qt/menurow.cc | 122 | ||||
-rw-r--r-- | src/skins-qt/menurow.h | 62 | ||||
-rw-r--r-- | src/skins-qt/menus.cc | 295 | ||||
-rw-r--r-- | src/skins-qt/menus.h (renamed from src/skins/preset-list.h) | 37 | ||||
-rw-r--r-- | src/skins-qt/monostereo.cc (renamed from src/skins/ui_skinned_monostereo.cc) | 29 | ||||
-rw-r--r-- | src/skins-qt/monostereo.h | 45 | ||||
-rw-r--r-- | src/skins-qt/number.cc | 60 | ||||
-rw-r--r-- | src/skins-qt/number.h (renamed from src/skins/ui_skinned_number.h) | 17 | ||||
-rw-r--r-- | src/skins-qt/playlist-slider.cc | 123 | ||||
-rw-r--r-- | src/skins-qt/playlist-slider.h (renamed from src/skins/ui_skinned_textbox.h) | 34 | ||||
-rw-r--r-- | src/skins-qt/playlist-widget.cc | 773 | ||||
-rw-r--r-- | src/skins-qt/playlist-widget.h | 98 | ||||
-rw-r--r-- | src/skins-qt/playlist.cc | 538 | ||||
-rw-r--r-- | src/skins-qt/playlist.h (renamed from src/skins/ui_playlist.h) | 17 | ||||
-rw-r--r-- | src/skins-qt/playstatus.cc | 63 | ||||
-rw-r--r-- | src/skins-qt/playstatus.h (renamed from src/skins/ui_skinned_playstatus.h) | 20 | ||||
-rw-r--r-- | src/skins-qt/plugin-window.cc | 208 | ||||
-rw-r--r-- | src/skins-qt/plugin-window.h (renamed from src/skins/preset-browser.h) | 20 | ||||
-rw-r--r-- | src/skins-qt/plugin.cc | 200 | ||||
-rw-r--r-- | src/skins-qt/plugin.h | 30 | ||||
-rw-r--r-- | src/skins-qt/skin-ini.cc | 278 | ||||
-rw-r--r-- | src/skins-qt/skin.cc | 531 | ||||
-rw-r--r-- | src/skins-qt/skin.h | 198 | ||||
-rw-r--r-- | src/skins-qt/skins_cfg.cc | 348 | ||||
-rw-r--r-- | src/skins-qt/skins_cfg.h | 57 | ||||
-rw-r--r-- | src/skins-qt/skinselector.cc | 129 | ||||
-rw-r--r-- | src/skins-qt/skinselector.h | 37 | ||||
-rw-r--r-- | src/skins-qt/svis.cc | 208 | ||||
-rw-r--r-- | src/skins-qt/textbox.cc | 294 | ||||
-rw-r--r-- | src/skins-qt/textbox.h | 82 | ||||
-rw-r--r-- | src/skins-qt/util.cc | 356 | ||||
-rw-r--r-- | src/skins-qt/util.h | 52 | ||||
-rw-r--r-- | src/skins-qt/view.cc | 291 | ||||
-rw-r--r-- | src/skins-qt/view.h | 56 | ||||
-rw-r--r-- | src/skins-qt/vis-callbacks.cc (renamed from src/skins/ui_main_evlisteners.cc) | 168 | ||||
-rw-r--r-- | src/skins-qt/vis-callbacks.h (renamed from src/skins/ui_main_evlisteners.h) | 10 | ||||
-rw-r--r-- | src/skins-qt/vis.cc | 318 | ||||
-rw-r--r-- | src/skins-qt/vis.h | 90 | ||||
-rw-r--r-- | src/skins-qt/widget.cc (renamed from src/skins/ui_skinned_window.h) | 41 | ||||
-rw-r--r-- | src/skins-qt/widget.h | 83 | ||||
-rw-r--r-- | src/skins-qt/window.cc | 161 | ||||
-rw-r--r-- | src/skins-qt/window.h | 76 | ||||
-rw-r--r-- | src/skins/Makefile | 175 | ||||
-rw-r--r-- | src/skins/actions-mainwin.h | 12 | ||||
-rw-r--r-- | src/skins/actions-playlist.h | 99 | ||||
-rw-r--r-- | src/skins/actions.cc | 282 | ||||
-rw-r--r-- | src/skins/button.cc | 132 | ||||
-rw-r--r-- | src/skins/button.h | 78 | ||||
-rw-r--r-- | src/skins/dock.cc | 356 | ||||
-rw-r--r-- | src/skins/drag-handle.cc | 86 | ||||
-rw-r--r-- | src/skins/drag-handle.h | 20 | ||||
-rw-r--r-- | src/skins/draw-compat.h | 50 | ||||
-rw-r--r-- | src/skins/eq-graph.cc (renamed from src/skins/ui_skinned_equalizer_graph.cc) | 72 | ||||
-rw-r--r-- | src/skins/eq-graph.h (renamed from src/skins/ui_skinned_equalizer_graph.h) | 13 | ||||
-rw-r--r-- | src/skins/eq-slider.cc | 127 | ||||
-rw-r--r-- | src/skins/eq-slider.h | 55 | ||||
-rw-r--r-- | src/skins/equalizer.cc | 289 | ||||
-rw-r--r-- | src/skins/equalizer.h | 38 | ||||
-rw-r--r-- | src/skins/hslider.cc | 129 | ||||
-rw-r--r-- | src/skins/hslider.h | 70 | ||||
-rw-r--r-- | src/skins/main.cc | 1227 | ||||
-rw-r--r-- | src/skins/main.h | 73 | ||||
-rw-r--r-- | src/skins/menurow.cc (renamed from src/skins/ui_skinned_menurow.cc) | 95 | ||||
-rw-r--r-- | src/skins/menurow.h (renamed from src/skins/ui_skinned_menurow.h) | 31 | ||||
-rw-r--r-- | src/skins/menus.cc | 103 | ||||
-rw-r--r-- | src/skins/menus.h | 6 | ||||
-rw-r--r-- | src/skins/monostereo.cc | 61 | ||||
-rw-r--r-- | src/skins/monostereo.h (renamed from src/skins/ui_skinned_monostereo.h) | 15 | ||||
-rw-r--r-- | src/skins/number.cc | 60 | ||||
-rw-r--r-- | src/skins/number.h | 40 | ||||
-rw-r--r-- | src/skins/playlist-slider.cc | 123 | ||||
-rw-r--r-- | src/skins/playlist-slider.h | 55 | ||||
-rw-r--r-- | src/skins/playlist-widget.cc | 813 | ||||
-rw-r--r-- | src/skins/playlist-widget.h | 97 | ||||
-rw-r--r-- | src/skins/playlist.cc | 551 | ||||
-rw-r--r-- | src/skins/playlist.h | 39 | ||||
-rw-r--r-- | src/skins/playstatus.cc (renamed from src/skins/ui_skinned_horizontal_slider.h) | 48 | ||||
-rw-r--r-- | src/skins/playstatus.h | 51 | ||||
-rw-r--r-- | src/skins/plugin-window.cc | 19 | ||||
-rw-r--r-- | src/skins/plugin-window.h | 8 | ||||
-rw-r--r-- | src/skins/plugin.cc | 121 | ||||
-rw-r--r-- | src/skins/plugin.h | 16 | ||||
-rw-r--r-- | src/skins/preset-browser.cc | 158 | ||||
-rw-r--r-- | src/skins/preset-list.cc | 462 | ||||
-rw-r--r-- | src/skins/search-select.cc | 204 | ||||
-rw-r--r-- | src/skins/skin-ini.cc | 278 | ||||
-rw-r--r-- | src/skins/skin.cc | 457 | ||||
-rw-r--r-- | src/skins/skin.h (renamed from src/skins/ui_skin.h) | 47 | ||||
-rw-r--r-- | src/skins/skins_cfg.cc | 192 | ||||
-rw-r--r-- | src/skins/skins_cfg.h | 15 | ||||
-rw-r--r-- | src/skins/skinselector.cc | 237 | ||||
-rw-r--r-- | src/skins/skinselector.h (renamed from src/skins/ui_skinselector.h) | 0 | ||||
-rw-r--r-- | src/skins/surface.cc | 6 | ||||
-rw-r--r-- | src/skins/svis.cc (renamed from src/skins/ui_svis.cc) | 88 | ||||
-rw-r--r-- | src/skins/textbox.cc | 311 | ||||
-rw-r--r-- | src/skins/textbox.h | 80 | ||||
-rw-r--r-- | src/skins/ui_equalizer.cc | 498 | ||||
-rw-r--r-- | src/skins/ui_main.cc | 1352 | ||||
-rw-r--r-- | src/skins/ui_playlist.cc | 1163 | ||||
-rw-r--r-- | src/skins/ui_skin.cc | 809 | ||||
-rw-r--r-- | src/skins/ui_skin_load_ini.cc | 315 | ||||
-rw-r--r-- | src/skins/ui_skinned_button.cc | 264 | ||||
-rw-r--r-- | src/skins/ui_skinned_button.h | 46 | ||||
-rw-r--r-- | src/skins/ui_skinned_equalizer_slider.cc | 191 | ||||
-rw-r--r-- | src/skins/ui_skinned_horizontal_slider.cc | 241 | ||||
-rw-r--r-- | src/skins/ui_skinned_number.cc | 93 | ||||
-rw-r--r-- | src/skins/ui_skinned_playlist.cc | 945 | ||||
-rw-r--r-- | src/skins/ui_skinned_playlist.h | 45 | ||||
-rw-r--r-- | src/skins/ui_skinned_playlist_slider.cc | 144 | ||||
-rw-r--r-- | src/skins/ui_skinned_playstatus.cc | 82 | ||||
-rw-r--r-- | src/skins/ui_skinned_textbox.cc | 412 | ||||
-rw-r--r-- | src/skins/ui_skinned_window.cc | 246 | ||||
-rw-r--r-- | src/skins/ui_skinselector.cc | 398 | ||||
-rw-r--r-- | src/skins/util.cc | 354 | ||||
-rw-r--r-- | src/skins/util.h | 25 | ||||
-rw-r--r-- | src/skins/view.cc | 164 | ||||
-rw-r--r-- | src/skins/view.h | 20 | ||||
-rw-r--r-- | src/skins/vis-callbacks.cc | 222 | ||||
-rw-r--r-- | src/skins/vis-callbacks.h | 26 | ||||
-rw-r--r-- | src/skins/vis.cc (renamed from src/skins/ui_vis.cc) | 195 | ||||
-rw-r--r-- | src/skins/vis.h (renamed from src/skins/ui_vis.h) | 43 | ||||
-rw-r--r-- | src/skins/widget.cc | 125 | ||||
-rw-r--r-- | src/skins/widget.h | 93 | ||||
-rw-r--r-- | src/skins/window.cc | 184 | ||||
-rw-r--r-- | src/skins/window.h | 81 | ||||
-rw-r--r-- | src/sndfile/plugin.cc | 45 | ||||
-rw-r--r-- | src/sndio-ng/sndio.cc | 41 | ||||
-rw-r--r-- | src/song-info-qt/song-info.cc | 9 | ||||
-rw-r--r-- | src/song_change/Makefile | 3 | ||||
-rw-r--r-- | src/song_change/formatter.cc | 99 | ||||
-rw-r--r-- | src/song_change/formatter.h | 22 | ||||
-rw-r--r-- | src/song_change/song_change.cc | 322 | ||||
-rw-r--r-- | src/statusicon-qt/Makefile | 13 | ||||
-rw-r--r-- | src/statusicon-qt/statusicon.cc | 192 | ||||
-rw-r--r-- | src/statusicon/statusicon.cc | 6 | ||||
-rw-r--r-- | src/vorbis/vcedit.cc | 2 | ||||
-rw-r--r-- | src/vorbis/vcedit.h | 4 | ||||
-rw-r--r-- | src/vorbis/vcupdate.cc | 3 | ||||
-rw-r--r-- | src/vorbis/vorbis.cc | 179 | ||||
-rw-r--r-- | src/vorbis/vorbis.h | 3 | ||||
-rw-r--r-- | src/vtx/Makefile | 8 | ||||
-rw-r--r-- | src/vtx/ayemu_vtxfile.h | 2 | ||||
-rw-r--r-- | src/vtx/info.cc | 4 | ||||
-rw-r--r-- | src/vtx/lh5dec.cc | 6 | ||||
-rw-r--r-- | src/vtx/vtx.cc | 2 | ||||
-rw-r--r-- | src/vtx/vtxfile.cc | 2 | ||||
-rw-r--r-- | src/wavpack/wavpack.cc | 2 | ||||
-rw-r--r-- | src/xsf/desmume/NDSSystem.h | 2 | ||||
-rw-r--r-- | src/xsf/plugin.cc | 2 | ||||
-rw-r--r-- | src/xspf/xspf.cc | 2 |
620 files changed, 33484 insertions, 25934 deletions
diff --git a/src/adplug/Makefile b/src/adplug/Makefile index 7ee162d..3239c1c 100644 --- a/src/adplug/Makefile +++ b/src/adplug/Makefile @@ -1,19 +1,22 @@ PLUGIN = adplug${PLUGIN_SUFFIX} SRCS = adplug-xmms.cc \ + binio/binfile.cc \ + binio/binio.cc \ + binio/binstr.cc \ core/fmopl.cc \ core/debug.cc \ core/adlibemu.cc \ core/adplug.cc \ core/emuopl.cc \ - core/fprovide.cc \ + core/fprovide.cc \ core/player.cc \ - core/database.cc \ + core/database.cc \ core/hsc.cc \ core/sng.cc \ core/imf.cc \ core/players.cc \ - core/protrack.cc \ + core/protrack.cc \ core/a2m.cc \ core/adtrack.cc \ core/amd.cc \ @@ -62,5 +65,4 @@ plugindir := ${plugindir}/${INPUT_PLUGIN_DIR} LD = ${CXX} CFLAGS += ${PLUGIN_CFLAGS} CXXFLAGS += ${PLUGIN_CFLAGS} -Wno-sign-compare -CPPFLAGS += ${PLUGIN_CPPFLAGS} ${BINIO_CFLAGS} -I../.. -I./core -LIBS += ${BINIO_LIBS} +CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../.. -I./core -I./binio diff --git a/src/adplug/adplug-xmms.cc b/src/adplug/adplug-xmms.cc index 89696cd..2cf0344 100644 --- a/src/adplug/adplug-xmms.cc +++ b/src/adplug/adplug-xmms.cc @@ -86,7 +86,6 @@ const char * const AdPlugXMMS::exts[] = { static struct { int freq = 44100l; bool bit16 = true, stereo = false, endless = false; - CPlayers players = CAdPlug::getPlayers(); } conf; // Player variables @@ -122,12 +121,6 @@ dbg_printf (const char *fmt, ...) #endif -static CPlayer * -factory (VFSFile & fd, Copl * newopl) -{ - return CAdPlug::factory (fd, newopl, conf.players); -} - /***** Main player (!! threaded !!) *****/ Tuple AdPlugXMMS::read_tuple (const char * filename, VFSFile & fd) @@ -135,10 +128,8 @@ Tuple AdPlugXMMS::read_tuple (const char * filename, VFSFile & fd) Tuple tuple; CSilentopl tmpopl; - if (!fd) - return tuple; - - CPlayer *p = factory (fd, &tmpopl); + CFileProvider fp (fd); + CPlayer *p = CAdPlug::factory (filename, &tmpopl, fp); if (p) { @@ -182,7 +173,8 @@ bool AdPlugXMMS::play (const char * filename, VFSFile & fd) // Try to load module dbg_printf ("factory, "); - if (!(plr.p = factory (fd, &opl))) + CFileProvider fp (fd); + if (!(plr.p = CAdPlug::factory (filename, &opl, fp))) { dbg_printf ("error!\n"); // MessageBox("AdPlug :: Error", "File could not be opened!", "Ok"); @@ -271,7 +263,8 @@ bool AdPlugXMMS::is_our_file (const char * filename, VFSFile & fd) { CSilentopl tmpopl; - CPlayer *p = factory (fd, &tmpopl); + CFileProvider fp (fd); + CPlayer *p = CAdPlug::factory (filename, &tmpopl, fp); dbg_printf ("adplug_is_our_file(\"%s\"): returned ", filename); @@ -306,21 +299,6 @@ bool AdPlugXMMS::init () conf.freq = aud_get_int (CFG_VERSION, "Frequency"); conf.endless = aud_get_bool (CFG_VERSION, "Endless"); - // Read file type exclusion list - dbg_printf ("exclusion, "); - { - String cfgstr = aud_get_str (CFG_VERSION, "Exclude"); - - if (cfgstr[0]) - { - StringBuf exclude = str_concat ({cfgstr, ":"}); - str_replace_char (exclude, ':', 0); - - for (char * p = exclude; * p; p += strlen (p) + 1) - conf.players.remove (conf.players.lookup_filetype (p)); - } - } - // Load database from disk and hand it to AdPlug dbg_printf ("database"); { @@ -358,18 +336,4 @@ void AdPlugXMMS::cleanup () aud_set_bool (CFG_VERSION, "Stereo", conf.stereo); aud_set_int (CFG_VERSION, "Frequency", conf.freq); aud_set_bool (CFG_VERSION, "Endless", conf.endless); - - dbg_printf ("exclude, "); - std::string exclude; - for (CPlayers::const_iterator i = CAdPlug::getPlayers().begin (); - i != CAdPlug::getPlayers().end (); i++) - if (find (conf.players.begin (), conf.players.end (), *i) == - conf.players.end ()) - { - if (!exclude.empty ()) - exclude += ":"; - exclude += (*i)->filetype; - } - - aud_set_str (CFG_VERSION, "Exclude", exclude.c_str ()); } diff --git a/src/adplug/binio/binfile.cc b/src/adplug/binio/binfile.cc new file mode 100644 index 0000000..ddffc2f --- /dev/null +++ b/src/adplug/binio/binfile.cc @@ -0,0 +1,247 @@ +/* + * 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; either + * version 2.1 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 + * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * binfile.h - Binary file I/O + * Copyright (C) 2002, 2003 Simon Peter <dn.tlp@gmx.net> + */ + +#include <stdio.h> +#include <errno.h> + +#include "binfile.h" + +/***** binfbase *****/ + +binfbase::binfbase() + : f(NULL) +{ +} + +binfbase::~binfbase() +{ + if(f != NULL) close(); +} + +void binfbase::close() +{ + if(f != NULL) { + if(fclose(f) == EOF) err |= Fatal; else f = NULL; + } else + err |= NotOpen; +} + +void binfbase::seek(long pos, Offset offs) +{ + int error = 0; + + if(f == NULL) { err |= NotOpen; return; } + + switch(offs) { + case Set: error = fseek(f, pos, SEEK_SET); break; + case Add: error = fseek(f, pos, SEEK_CUR); break; + case End: error = fseek(f, pos, SEEK_END); break; + } + + if(error == -1) err |= Fatal; +} + +long binfbase::pos() +{ + long pos; + + if(f == NULL) { err |= NotOpen; return 0; } + + pos = ftell(f); + + if(pos == -1) { + err |= Fatal; + return 0; + } else + return pos; +} + +/***** binifstream *****/ + +binifstream::binifstream() +{ +} + +binifstream::binifstream(const char *filename, const Mode mode) +{ + open(filename, mode); +} + +#if BINIO_ENABLE_STRING +binifstream::binifstream(const std::string &filename, const Mode mode) +{ + open(filename, mode); +} +#endif + +binifstream::~binifstream() +{ +} + +void binifstream::open(const char *filename, const Mode mode) +{ + f = fopen(filename, "rb"); + + if(f == NULL) + switch(errno) { + case ENOENT: err |= NotFound; break; + case EACCES: err |= Denied; break; + default: err |= NotOpen; break; + } +} + +#if BINIO_ENABLE_STRING +void binifstream::open(const std::string &filename, const Mode mode) +{ + open(filename.c_str(), mode); +} +#endif + +binifstream::Byte binifstream::getByte() +{ + int read; + + if(f != NULL) { + read = fgetc(f); + if(read == EOF) err |= Eof; + return (Byte)read; + } else { + err |= NotOpen; + return 0; + } +} + +/***** binofstream *****/ + +binofstream::binofstream() +{ +} + +binofstream::binofstream(const char *filename, const Mode mode) +{ + open(filename, mode); +} + +#if BINIO_ENABLE_STRING +binofstream::binofstream(const std::string &filename, const Mode mode) +{ + open(filename, mode); +} +#endif + +binofstream::~binofstream() +{ +} + +void binofstream::open(const char *filename, const Mode mode) +{ + const char *modestr = "wb"; + + // Check if append mode is desired + if(mode & Append) modestr = "ab"; + + f = fopen(filename, modestr); + + if(f == NULL) + switch(errno) { + case EEXIST: + case EACCES: + case EROFS: + err |= Denied; + break; + case ENOENT: err |= NotFound; break; + default: err |= NotOpen; break; + } +} + +#if BINIO_ENABLE_STRING +void binofstream::open(const std::string &filename, const Mode mode) +{ + open(filename.c_str(), mode); +} +#endif + +void binofstream::putByte(Byte b) +{ + if(f == NULL) { err |= NotOpen; return; } + + if(fputc(b, f) == EOF) + err |= Fatal; +} + +/***** binfstream *****/ + +binfstream::binfstream() +{ +} + +binfstream::binfstream(const char *filename, const Mode mode) +{ + open(filename, mode); +} + +#if BINIO_ENABLE_STRING +binfstream::binfstream(const std::string &filename, const Mode mode) +{ + open(filename, mode); +} +#endif + +binfstream::~binfstream() +{ +} + +void binfstream::open(const char *filename, const Mode mode) +{ + char modestr[] = "w+b"; // Create & at beginning + int ferror = 0; + + // Apply desired mode + if(mode & NoCreate) { + if(!(mode & Append)) + modestr[0] = 'r'; // NoCreate & at beginning + } else + if(mode & Append) // Create & append + modestr[0] = 'a'; + + f = fopen(filename, modestr); + + // NoCreate & append (emulated -- not possible with standard C fopen()) + if(f != NULL && (mode & Append) && (mode & NoCreate)) + ferror = fseek(f, 0, SEEK_END); + + if(f == NULL || ferror == -1) { + switch(errno) { + case EEXIST: + case EACCES: + case EROFS: + err |= Denied; + break; + case ENOENT: err |= NotFound; break; + default: err |= NotOpen; break; + } + } +} + +#if BINIO_ENABLE_STRING +void binfstream::open(const std::string &filename, const Mode mode) +{ + open(filename.c_str(), mode); +} +#endif diff --git a/src/adplug/binio/binfile.h b/src/adplug/binio/binfile.h new file mode 100644 index 0000000..f64a5aa --- /dev/null +++ b/src/adplug/binio/binfile.h @@ -0,0 +1,110 @@ +/* + * 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; either + * version 2.1 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 + * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * binfile.h - Binary file I/O + * Copyright (C) 2002, 2003 Simon Peter <dn.tlp@gmx.net> + */ + +#ifndef H_BINIO_BINFILE +#define H_BINIO_BINFILE + +#include <stdio.h> + +#include "binio.h" + +class binfbase: virtual public binio +{ +public: + typedef enum { + Append = 1 << 0, + NoCreate = 1 << 1 + } ModeFlags; + + typedef int Mode; + + binfbase(); + virtual ~binfbase(); + + virtual void open(const char *filename, const Mode mode) = 0; +#if BINIO_ENABLE_STRING + virtual void open(const std::string &filename, const Mode mode) = 0; +#endif + void close(); + + virtual void seek(long pos, Offset offs = Set); + virtual long pos(); + +protected: + FILE *f; +}; + +class binifstream: public binistream, virtual public binfbase +{ +public: + binifstream(); + binifstream(const char *filename, const Mode mode = NoCreate); +#if BINIO_ENABLE_STRING + binifstream(const std::string &filename, const Mode mode = NoCreate); +#endif + + virtual ~binifstream(); + + virtual void open(const char *filename, const Mode mode = NoCreate); +#if BINIO_ENABLE_STRING + virtual void open(const std::string &filename, const Mode mode = NoCreate); +#endif + +protected: + virtual Byte getByte(); +}; + +class binofstream: public binostream, virtual public binfbase +{ +public: + binofstream(); + binofstream(const char *filename, const Mode mode = 0); +#if BINIO_ENABLE_STRING + binofstream(const std::string &filename, const Mode mode = 0); +#endif + + virtual ~binofstream(); + + virtual void open(const char *filename, const Mode mode = 0); +#if BINIO_ENABLE_STRING + virtual void open(const std::string &filename, const Mode mode = 0); +#endif + +protected: + virtual void putByte(Byte b); +}; + +class binfstream: public binifstream, public binofstream +{ +public: + binfstream(); + binfstream(const char *filename, const Mode mode = 0); +#if BINIO_ENABLE_STRING + binfstream(const std::string &filename, const Mode mode = 0); +#endif + + virtual ~binfstream(); + + virtual void open(const char *filename, const Mode mode = 0); +#if BINIO_ENABLE_STRING + virtual void open(const std::string &filename, const Mode mode = 0); +#endif +}; + +#endif diff --git a/src/adplug/binio/binio.cc b/src/adplug/binio/binio.cc new file mode 100644 index 0000000..80a5765 --- /dev/null +++ b/src/adplug/binio/binio.cc @@ -0,0 +1,298 @@ +/* + * 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; either + * version 2.1 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 + * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * binio.cpp - Binary stream I/O classes + * Copyright (C) 2002, 2003 Simon Peter <dn.tlp@gmx.net> + */ + +#include <string.h> + +#include "binio.h" + +/***** Defines *****/ + +#if BINIO_ENABLE_STRING +// String buffer size for std::string readString() method +#define STRINGBUFSIZE 256 +#endif + +/***** binio *****/ + +#ifdef WORDS_BIGENDIAN +const binio::Flags binio::system_flags = BigEndian | FloatIEEE; +#else +const binio::Flags binio::system_flags = FloatIEEE; +#endif + +binio::binio() + : my_flags(system_flags), err(NoError) +{ +} + +binio::~binio() +{ +} + +void binio::setFlag(Flag f, bool set) +{ + if(set) + my_flags |= f; + else + my_flags &= !f; +} + +bool binio::getFlag(Flag f) +{ + return (my_flags & f ? true : false); +} + +binio::Error binio::error() +{ + Error e = err; + + err = NoError; + return e; +} + +bool binio::eof() +{ + return (err & Eof ? true : false); +} + +/***** binistream *****/ + +binistream::binistream() +{ +} + +binistream::~binistream() +{ +} + +binistream::Int binistream::readInt(unsigned int size) +{ + unsigned int i; + Int val = 0, in; + + // Check if 'size' doesn't exceed our system's biggest type. + if(size > sizeof(Int)) { + err |= Unsupported; + return 0; + } + + for(i = 0; i < size; i++) { + in = getByte(); + if(getFlag(BigEndian)) + val <<= 8; + else + in <<= i * 8; + val |= in; + } + + return val; +} + +binistream::Float binistream::readFloat(FType ft) +{ + if(getFlag(FloatIEEE)) { // Read IEEE-754 floating-point value + unsigned int i, size = 0; + FloatData in; + bool swap; + + // Determine appropriate size for given type. + switch(ft) { + case Single: size = 4; break; // 32 bits + case Double: size = 8; break; // 64 bits + } + + // Determine byte ordering + swap = getFlag(BigEndian) ^ (system_flags & BigEndian); + + // Read the float byte by byte, converting endianess + for(i = 0; i < size; i++) + if(swap) + in.b[size - i - 1] = getByte(); + else + in.b[i] = getByte(); + + // Let the hardware do the conversion + switch(ft) { + case Single: return in.f; + case Double: return in.d; + } + } + + // User tried to read a (yet) unsupported floating-point type. Bail out. + err |= Unsupported; return 0.0; +} + +unsigned long binistream::readString(char *str, unsigned long maxlen) +{ + unsigned long i; + + for(i = 0; i < maxlen; i++) { + str[i] = (char)getByte(); + if(err) { str[i] = '\0'; return i; } + } + + return maxlen; +} + +unsigned long binistream::readString(char *str, unsigned long maxlen, + const char delim) +{ + unsigned long i; + + for(i = 0; i < maxlen; i++) { + str[i] = (char)getByte(); + if(str[i] == delim || err) { str[i] = '\0'; return i; } + } + + str[maxlen] = '\0'; + return maxlen; +} + +#if BINIO_ENABLE_STRING +std::string binistream::readString(const char delim) +{ + char buf[STRINGBUFSIZE + 1]; + std::string tempstr; + unsigned long read; + + do { + read = readString(buf, STRINGBUFSIZE, delim); + tempstr.append(buf, read); + } while(read == STRINGBUFSIZE); + + return tempstr; +} +#endif + +binistream::Int binistream::peekInt(unsigned int size) +{ + Int val = readInt(size); + if(!err) seek(-(long)size, Add); + return val; +} + +binistream::Float binistream::peekFloat(FType ft) +{ + Float val = readFloat(ft); + + if(!err) + switch(ft) { + case Single: seek(-4, Add); break; + case Double: seek(-8, Add); break; + } + + return val; +} + +bool binistream::ateof() +{ + Error olderr = err; // Save current error state + bool eof_then; + + peekInt(1); + eof_then = eof(); // Get error state of next byte + err = olderr; // Restore original error state + return eof_then; +} + +void binistream::ignore(unsigned long amount) +{ + unsigned long i; + + for(i = 0; i < amount; i++) + getByte(); +} + +/***** binostream *****/ + +binostream::binostream() +{ +} + +binostream::~binostream() +{ +} + +void binostream::writeInt(Int val, unsigned int size) +{ + unsigned int i; + + // Check if 'size' doesn't exceed our system's biggest type. + if(size > sizeof(Int)) { err |= Unsupported; return; } + + for(i = 0; i < size; i++) { + if(getFlag(BigEndian)) + putByte((val >> (size - i - 1) * 8) & 0xff); + else { + putByte(val & 0xff); + val >>= 8; + } + } +} + +void binostream::writeFloat(Float f, FType ft) +{ + if(getFlag(FloatIEEE)) { // Write IEEE-754 floating-point value + unsigned int i, size = 0; + FloatData out; + bool swap; + + // Hardware could be big or little endian, convert appropriately + swap = getFlag(BigEndian) ^ (system_flags & BigEndian); + + // Determine appropriate size for given type and convert by hardware + switch(ft) { + case Single: size = 4; out.f = f; break; // 32 bits + case Double: size = 8; out.d = f; break; // 64 bits + } + + // Write the float byte by byte, converting endianess + for(i = 0; i < size; i++) + if(swap) + putByte(out.b[size - i - 1]); + else + putByte(out.b[i]); + + return; // We're done. + } + + // User tried to write an unsupported floating-point type. Bail out. + err |= Unsupported; +} + +unsigned long binostream::writeString(const char *str, unsigned long amount) +{ + unsigned int i; + + if(!amount) amount = strlen(str); + + for(i = 0; i < amount; i++) { + putByte(str[i]); + if(err) return i; + } + + return amount; +} + +#if BINIO_ENABLE_STRING +unsigned long binostream::writeString(const std::string &str) +{ + return writeString(str.c_str()); +} +#endif diff --git a/src/adplug/binio/binio.h b/src/adplug/binio/binio.h new file mode 100644 index 0000000..311572f --- /dev/null +++ b/src/adplug/binio/binio.h @@ -0,0 +1,137 @@ +/* -*-C++-*- + * 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; either + * version 2.1 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 + * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * binio.h - Binary stream I/O classes + * Copyright (C) 2002, 2003 Simon Peter <dn.tlp@gmx.net> + */ + +#ifndef H_BINIO_BINIO +#define H_BINIO_BINIO + +/***** Configuration *****/ + +// BINIO_ENABLE_STRING - Build std::string supporting methods +// +// Set to 1 to build std::string supporting methods. You need the STL to +// do this. +#define BINIO_ENABLE_STRING 1 + +/***** Implementation *****/ + +#if BINIO_ENABLE_STRING +#include <string> +#endif + +class binio +{ +public: + typedef enum { + BigEndian = 1 << 0, + FloatIEEE = 1 << 1 + } Flag; + + typedef enum { + NoError = 0, + Fatal = 1 << 0, + Unsupported = 1 << 1, + NotOpen = 1 << 2, + Denied = 1 << 3, + NotFound = 1 << 4, + Eof = 1 << 5 + } ErrorCode; + + typedef enum { Set, Add, End } Offset; + typedef enum { Single, Double } FType; + typedef int Error; + + binio(); + virtual ~binio(); + + void setFlag(Flag f, bool set = true); + bool getFlag(Flag f); + + Error error(); + bool eof(); + + virtual void seek(long, Offset = Set) = 0; + virtual long pos() = 0; + +protected: + typedef long long Int; + typedef long double Float; + typedef unsigned char Byte; // has to be unsigned! + + typedef int Flags; + + Flags my_flags; + static const Flags system_flags; + Error err; + + union FloatData { + Byte b[8]; + double d; + float f; + }; +}; + +class binistream: virtual public binio +{ +public: + binistream(); + virtual ~binistream(); + + Int readInt(unsigned int size); + Float readFloat(FType ft); + unsigned long readString(char *str, unsigned long amount); + unsigned long readString(char *str, unsigned long maxlen, const char delim); +#if BINIO_ENABLE_STRING + std::string readString(const char delim = '\0'); +#endif + + Int peekInt(unsigned int size); + Float peekFloat(FType ft); + + bool ateof(); + void ignore(unsigned long amount = 1); + +protected: + virtual Byte getByte() = 0; +}; + +class binostream: virtual public binio +{ +public: + binostream(); + virtual ~binostream(); + + void writeInt(Int val, unsigned int size); + void writeFloat(Float f, FType ft); + unsigned long writeString(const char *str, unsigned long amount = 0); +#if BINIO_ENABLE_STRING + unsigned long writeString(const std::string &str); +#endif + +protected: + virtual void putByte(Byte) = 0; +}; + +class binstream: public binistream, public binostream +{ +public: + binstream(); + virtual ~binstream(); +}; + +#endif diff --git a/src/adplug/binio/binio_virtual.h b/src/adplug/binio/binio_virtual.h new file mode 100644 index 0000000..08a6275 --- /dev/null +++ b/src/adplug/binio/binio_virtual.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2006 William Pitcock <nenolod -at- atheme.org> + * This code is in the public domain. + */ + +#ifndef __BINIO_VIRTUAL__ +#define __BINIO_VIRTUAL__ + +#include "binio.h" + +#include <libaudcore/vfs.h> + +class vfsistream : public binistream { +private: + VFSFile *fd = nullptr; + VFSFile own; + +public: + vfsistream(VFSFile *fd = nullptr) : + fd(fd) {} + + vfsistream(std::string &file) { + if ((own = VFSFile(file.c_str(), "r"))) + fd = &own; + else + err |= NotFound; + } + + Byte getByte() { + Byte b = (Byte)-1; + if (fd->fread(&b, 1, 1) != 1) + err |= Eof; + return b; + } + + void seek(long pos, Offset offs = Set) { + VFSSeekType wh = (offs == Add) ? VFS_SEEK_CUR : (offs == End) ? VFS_SEEK_END : VFS_SEEK_SET; + if (fd->fseek (pos, wh)) + err |= Eof; + } + + long pos() { + return fd->ftell (); + } + + unsigned long size() { + return aud::max(fd->fsize(), (int64_t)0); + } +}; + +#endif diff --git a/src/adplug/binio/binstr.cc b/src/adplug/binio/binstr.cc new file mode 100644 index 0000000..2beb79f --- /dev/null +++ b/src/adplug/binio/binstr.cc @@ -0,0 +1,114 @@ +/* + * 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; either + * version 2.1 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 + * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * binstr.cpp - Binary I/O on standard C strings in memory + * Copyright (C) 2003 Simon Peter <dn.tlp@gmx.net> + */ + +#include "binstr.h" + +/***** binsbase *****/ + +binsbase::binsbase(void *str, unsigned long len) + : data((Byte *)str), spos((Byte *)str), length(len) +{ +} + +binsbase::~binsbase() +{ +} + +void binsbase::seek(long p, Offset offs) +{ + switch(offs) { + case Set: spos = data + p; break; + case Add: spos += p; break; + case End: spos = data + length - 1 + p; break; + } + + // Seek before start of data + if(spos < data) { + err |= Eof; + spos = data; + return; + } + + // Seek after end of data + if(spos - data >= length) { + err |= Eof; + spos = data + length - 1; + } +} + +long binsbase::pos() +{ + return (long)(spos - data); +} + +/***** binisstream *****/ + +binisstream::binisstream(void *str, unsigned long len) + : binsbase(str, len) +{ +} + +binisstream::~binisstream() +{ +} + +binisstream::Byte binisstream::getByte() +{ + Byte in = 0; + + if(spos - data >= length) + err |= Eof; + else { + in = *spos; + spos++; + } + + return in; +} + +/***** binosstream *****/ + +binosstream::binosstream(void *str, unsigned long len) + : binsbase(str, len) +{ +} + +binosstream::~binosstream() +{ +} + +void binosstream::putByte(Byte b) +{ + *spos = b; + spos++; + + if(spos - data >= length) + spos = data + length - 1; +} + +/***** binsstream *****/ + +binsstream::binsstream(void *str, unsigned long len) + : binsbase(str, len), binisstream(str, len), binosstream(str, len) +{ +} + +binsstream::~binsstream() +{ +} diff --git a/src/adplug/binio/binstr.h b/src/adplug/binio/binstr.h new file mode 100644 index 0000000..f8f1123 --- /dev/null +++ b/src/adplug/binio/binstr.h @@ -0,0 +1,66 @@ +/* + * 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; either + * version 2.1 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 + * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * binstr.h - Binary I/O on standard C strings in memory + * Copyright (C) 2003 Simon Peter <dn.tlp@gmx.net> + */ + +#ifndef H_BINIO_BINSTR +#define H_BINIO_BINSTR + +#include "binio.h" + +class binsbase: virtual public binio +{ +public: + binsbase(void *str, unsigned long len); + virtual ~binsbase(); + + virtual void seek(long p, Offset offs = Set); + virtual long pos(); + +protected: + Byte *data, *spos; + long length; +}; + +class binisstream: public binistream, virtual public binsbase +{ +public: + binisstream(void *str, unsigned long len); + virtual ~binisstream(); + +protected: + virtual Byte getByte(); +}; + +class binosstream: public binostream, virtual public binsbase +{ +public: + binosstream(void *str, unsigned long len); + virtual ~binosstream(); + +protected: + virtual void putByte(Byte b); +}; + +class binsstream: public binisstream, public binosstream +{ +public: + binsstream(void *str, unsigned long len); + virtual ~binsstream(); +}; + +#endif diff --git a/src/adplug/core/a2m.cc b/src/adplug/core/a2m.cc index 4c446c2..3ec924a 100644 --- a/src/adplug/core/a2m.cc +++ b/src/adplug/core/a2m.cc @@ -29,273 +29,209 @@ * Following commands are ignored: Gxy, Hxy, Kxy - &xy */ -#include <string.h> - +#include <cstring> #include "a2m.h" -const unsigned int - Ca2mLoader::MAXFREQ = 2000, - Ca2mLoader::MINCOPY = ADPLUG_A2M_MINCOPY, - Ca2mLoader::MAXCOPY = ADPLUG_A2M_MAXCOPY, - Ca2mLoader::COPYRANGES = ADPLUG_A2M_COPYRANGES, - Ca2mLoader::CODESPERRANGE = ADPLUG_A2M_CODESPERRANGE, - Ca2mLoader::TERMINATE = 256, - Ca2mLoader::FIRSTCODE = ADPLUG_A2M_FIRSTCODE, - Ca2mLoader::MAXCODE = FIRSTCODE + COPYRANGES * CODESPERRANGE - 1, - Ca2mLoader::SUCCMAX = MAXCODE + 1, - Ca2mLoader::TWICEMAX = ADPLUG_A2M_TWICEMAX, - Ca2mLoader::ROOT = 1, Ca2mLoader::MAXBUF = 42 * 1024, - Ca2mLoader::MAXDISTANCE = 21389, Ca2mLoader::MAXSIZE = 21389 + MAXCOPY; - -const unsigned short -Ca2mLoader::bitvalue[14] = - { 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192 }; - -const signed short -Ca2mLoader::copybits[COPYRANGES] = { 4, 6, 8, 10, 12, 14 }; - -const signed short -Ca2mLoader::copymin[COPYRANGES] = { 0, 16, 80, 336, 1360, 5456 }; - -CPlayer * -Ca2mLoader::factory (Copl * newopl) +const unsigned int Ca2mLoader::MAXFREQ = 2000, +Ca2mLoader::MINCOPY = ADPLUG_A2M_MINCOPY, +Ca2mLoader::MAXCOPY = ADPLUG_A2M_MAXCOPY, +Ca2mLoader::COPYRANGES = ADPLUG_A2M_COPYRANGES, +Ca2mLoader::CODESPERRANGE = ADPLUG_A2M_CODESPERRANGE, +Ca2mLoader::TERMINATE = 256, +Ca2mLoader::FIRSTCODE = ADPLUG_A2M_FIRSTCODE, +Ca2mLoader::MAXCHAR = FIRSTCODE + COPYRANGES * CODESPERRANGE - 1, +Ca2mLoader::SUCCMAX = MAXCHAR + 1, +Ca2mLoader::TWICEMAX = ADPLUG_A2M_TWICEMAX, +Ca2mLoader::ROOT = 1, Ca2mLoader::MAXBUF = 42 * 1024, +Ca2mLoader::MAXDISTANCE = 21389, Ca2mLoader::MAXSIZE = 21389 + MAXCOPY; + +const unsigned short Ca2mLoader::bitvalue[14] = + {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192}; + +const signed short Ca2mLoader::copybits[COPYRANGES] = + {4, 6, 8, 10, 12, 14}; + +const signed short Ca2mLoader::copymin[COPYRANGES] = + {0, 16, 80, 336, 1360, 5456}; + +CPlayer *Ca2mLoader::factory(Copl *newopl) { - return new Ca2mLoader (newopl); + return new Ca2mLoader(newopl); } -bool -Ca2mLoader::load (VFSFile & fd, const CFileProvider & fp) +bool Ca2mLoader::load(const std::string &filename, const CFileProvider &fp) { - binistream *f = fp.open (fd); - if (!f) - return false; + binistream *f = fp.open(filename); if(!f) return false; char id[10]; - int i, j, k, t; + int i,j,k,t; unsigned int l; unsigned char *org = nullptr, *orgptr, flags = 0, numpats, version; unsigned long alength; unsigned short len[9], *secdata, *secptr; - const unsigned char convfx[16] = - { 0, 1, 2, 23, 24, 3, 5, 4, 6, 9, 17, 13, 11, 19, 7, 14 }; - const unsigned char convinf1[16] = - { 0, 1, 2, 6, 7, 8, 9, 4, 5, 3, 10, 11, 12, 13, 14, 15 }; - const unsigned char newconvfx[] = - { 0, 1, 2, 3, 4, 5, 6, 23, 24, 21, 10, 11, 17, 13, 7, 19, - 255, 255, 22, 25, 255, 15, 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 14, 255 - }; + const unsigned char convfx[16] = {0,1,2,23,24,3,5,4,6,9,17,13,11,19,7,14}; + const unsigned char convinf1[16] = {0,1,2,6,7,8,9,4,5,3,10,11,12,13,14,15}; + const unsigned char newconvfx[] = {0,1,2,3,4,5,6,23,24,21,10,11,17,13,7,19, + 255,255,22,25,255,15,255,255,255,255,255, + 255,255,255,255,255,255,255,255,14,255}; // read header - f->readString (id, 10); - f->readInt (4); - version = f->readInt (1); - numpats = f->readInt (1); + f->readString(id, 10); (void)f->readInt(4); + version = f->readInt(1); numpats = f->readInt(1); // file validation section - if (strncmp (id, "_A2module_", 10) || (version != 1 && version != 5 && - version != 4 && version != 8)) - { - fp.close (f); + if(strncmp(id,"_A2module_",10) || (version != 1 && version != 5 && + version != 4 && version != 8)) { + fp.close(f); return false; } // load, depack & convert section - nop = numpats; - length = 128; - restartpos = 0; - if (version < 5) - { - for (i = 0; i < 5; i++) - len[i] = f->readInt (2); + nop = numpats; length = 128; restartpos = 0; + if(version < 5) { + for(i=0;i<5;i++) len[i] = f->readInt(2); t = 9; - } - else - { // version >= 5 - for (i = 0; i < 9; i++) - len[i] = f->readInt (2); + } else { // version >= 5 + for(i=0;i<9;i++) len[i] = f->readInt(2); t = 18; } // block 0 - secdata = new unsigned short[len[0] / 2]; - if (version == 1 || version == 5) - { - for (i = 0; i < len[0] / 2; i++) - secdata[i] = f->readInt (2); - org = new unsigned char[MAXBUF]; - orgptr = org; - sixdepak (secdata, org, len[0]); - } - else - { - orgptr = (unsigned char *) secdata; - for (i = 0; i < len[0]; i++) - orgptr[i] = f->readInt (1); + secdata = new unsigned short [len[0] / 2]; + if(version == 1 || version == 5) { + for(i=0;i<len[0]/2;i++) secdata[i] = f->readInt(2); + org = new unsigned char [MAXBUF]; orgptr = org; + sixdepak(secdata,org,len[0]); + } else { + orgptr = (unsigned char *)secdata; + for(i=0;i<len[0];i++) orgptr[i] = f->readInt(1); } - memcpy (songname, orgptr, 43); - orgptr += 43; - memcpy (author, orgptr, 43); - orgptr += 43; - memcpy (instname, orgptr, 250 * 33); - orgptr += 250 * 33; - - for (i = 0; i < 250; i++) - { // instruments - inst[i].data[0] = *(orgptr + i * 13 + 10); - inst[i].data[1] = *(orgptr + i * 13); - inst[i].data[2] = *(orgptr + i * 13 + 1); - inst[i].data[3] = *(orgptr + i * 13 + 4); - inst[i].data[4] = *(orgptr + i * 13 + 5); - inst[i].data[5] = *(orgptr + i * 13 + 6); - inst[i].data[6] = *(orgptr + i * 13 + 7); - inst[i].data[7] = *(orgptr + i * 13 + 8); - inst[i].data[8] = *(orgptr + i * 13 + 9); - inst[i].data[9] = *(orgptr + i * 13 + 2); - inst[i].data[10] = *(orgptr + i * 13 + 3); - if (version < 5) - inst[i].misc = *(orgptr + i * 13 + 11); - else - { // version >= 5 -> OPL3 format - int pan = *(orgptr + i * 13 + 11); - - if (pan) - inst[i].data[0] |= (pan & 3) << 4; // set pan + memcpy(songname,orgptr,43); orgptr += 43; + memcpy(author,orgptr,43); orgptr += 43; + memcpy(instname,orgptr,250*33); orgptr += 250*33; + + for(i=0;i<250;i++) { // instruments + inst[i].data[0] = *(orgptr+i*13+10); + inst[i].data[1] = *(orgptr+i*13); + inst[i].data[2] = *(orgptr+i*13+1); + inst[i].data[3] = *(orgptr+i*13+4); + inst[i].data[4] = *(orgptr+i*13+5); + inst[i].data[5] = *(orgptr+i*13+6); + inst[i].data[6] = *(orgptr+i*13+7); + inst[i].data[7] = *(orgptr+i*13+8); + inst[i].data[8] = *(orgptr+i*13+9); + inst[i].data[9] = *(orgptr+i*13+2); + inst[i].data[10] = *(orgptr+i*13+3); + + if(version < 5) + inst[i].misc = *(orgptr+i*13+11); + else { // version >= 5 -> OPL3 format + int pan = *(orgptr+i*13+11); + + if(pan) + inst[i].data[0] |= (pan & 3) << 4; // set pan else - inst[i].data[0] |= 48; // enable both speakers + inst[i].data[0] |= 48; // enable both speakers } - inst[i].slide = *(orgptr + i * 13 + 12); + inst[i].slide = *(orgptr+i*13+12); } - orgptr += 250 * 13; - memcpy (order, orgptr, 128); - orgptr += 128; - bpm = *orgptr; - orgptr++; - initspeed = *orgptr; - orgptr++; - if (version >= 5) - flags = *orgptr; - if (version == 1 || version == 5) - delete[]org; - delete[]secdata; + orgptr += 250*13; + memcpy(order,orgptr,128); orgptr += 128; + bpm = *orgptr; orgptr++; + initspeed = *orgptr; orgptr++; + if(version >= 5) flags = *orgptr; + if(version == 1 || version == 5) delete [] org; + delete [] secdata; // blocks 1-4 or 1-8 alength = len[1]; - for (i = 0; i < (version < 5 ? numpats / 16 : numpats / 8); i++) - alength += len[i + 2]; - - secdata = new unsigned short[alength / 2]; - if (version == 1 || version == 5) - { - for (l = 0; l < alength / 2; l++) - secdata[l] = f->readInt (2); - org = new unsigned char[MAXBUF * (numpats / (version == 1 ? 16 : 8) + 1)]; - orgptr = org; - secptr = secdata; - orgptr += sixdepak (secptr, orgptr, len[1]); - secptr += len[1] / 2; - if (version == 1) - { - if (numpats > 16) - orgptr += sixdepak (secptr, orgptr, len[2]); - secptr += len[2] / 2; - if (numpats > 32) - orgptr += sixdepak (secptr, orgptr, len[3]); - secptr += len[3] / 2; - if (numpats > 48) - sixdepak (secptr, orgptr, len[4]); + for(i = 0; i < (version < 5 ? numpats / 16 : numpats / 8); i++) + alength += len[i+2]; + + secdata = new unsigned short [alength / 2]; + if(version == 1 || version == 5) { + for(l=0;l<alength/2;l++) secdata[l] = f->readInt(2); + org = new unsigned char [MAXBUF * (numpats / (version == 1 ? 16 : 8) + 1)]; + orgptr = org; secptr = secdata; + orgptr += sixdepak(secptr,orgptr,len[1]); secptr += len[1] / 2; + if(version == 1) { + if(numpats > 16) + orgptr += sixdepak(secptr,orgptr,len[2]); secptr += len[2] / 2; + if(numpats > 32) + orgptr += sixdepak(secptr,orgptr,len[3]); secptr += len[3] / 2; + if(numpats > 48) + sixdepak(secptr,orgptr,len[4]); + } else { + if(numpats > 8) + orgptr += sixdepak(secptr,orgptr,len[2]); secptr += len[2] / 2; + if(numpats > 16) + orgptr += sixdepak(secptr,orgptr,len[3]); secptr += len[3] / 2; + if(numpats > 24) + orgptr += sixdepak(secptr,orgptr,len[4]); secptr += len[4] / 2; + if(numpats > 32) + orgptr += sixdepak(secptr,orgptr,len[5]); secptr += len[5] / 2; + if(numpats > 40) + orgptr += sixdepak(secptr,orgptr,len[6]); secptr += len[6] / 2; + if(numpats > 48) + orgptr += sixdepak(secptr,orgptr,len[7]); secptr += len[7] / 2; + if(numpats > 56) + sixdepak(secptr,orgptr,len[8]); } - else - { - if (numpats > 8) - orgptr += sixdepak (secptr, orgptr, len[2]); - secptr += len[2] / 2; - if (numpats > 16) - orgptr += sixdepak (secptr, orgptr, len[3]); - secptr += len[3] / 2; - if (numpats > 24) - orgptr += sixdepak (secptr, orgptr, len[4]); - secptr += len[4] / 2; - if (numpats > 32) - orgptr += sixdepak (secptr, orgptr, len[5]); - secptr += len[5] / 2; - if (numpats > 40) - orgptr += sixdepak (secptr, orgptr, len[6]); - secptr += len[6] / 2; - if (numpats > 48) - orgptr += sixdepak (secptr, orgptr, len[7]); - secptr += len[7] / 2; - if (numpats > 56) - sixdepak (secptr, orgptr, len[8]); - } - delete[]secdata; - secdata = 0; - } - else - { - org = (unsigned char *) secdata; - for (l = 0; l < alength; l++) - org[l] = f->readInt (1); + delete [] secdata; + } else { + org = (unsigned char *)secdata; + for(l=0;l<alength;l++) org[l] = f->readInt(1); } - if (version < 5) - { - for (i = 0; i < numpats; i++) - for (j = 0; j < 64; j++) - for (k = 0; k < 9; k++) - { + if(version < 5) { + for(i=0;i<numpats;i++) + for(j=0;j<64;j++) + for(k=0;k<9;k++) { struct Tracks *track = &tracks[i * 9 + k][j]; - unsigned char *o = &org[i * 64 * t * 4 + j * t * 4 + k * 4]; + unsigned char *o = &org[i*64*t*4+j*t*4+k*4]; track->note = o[0] == 255 ? 127 : o[0]; track->inst = o[1]; track->command = convfx[o[2]]; track->param2 = o[3] & 0x0f; - if (track->command != 14) + if(track->command != 14) track->param1 = o[3] >> 4; - else - { + else { track->param1 = convinf1[o[3] >> 4]; - if (track->param1 == 15 && !track->param2) - { // convert key-off + if(track->param1 == 15 && !track->param2) { // convert key-off track->command = 8; track->param1 = 0; track->param2 = 0; } } - if (track->command == 14) - { - switch (track->param1) - { - case 2: // convert define waveform + if(track->command == 14) { + switch(track->param1) { + case 2: // convert define waveform track->command = 25; track->param1 = track->param2; track->param2 = 0xf; break; - case 8: // convert volume slide up + case 8: // convert volume slide up track->command = 26; track->param1 = track->param2; track->param2 = 0; break; - case 9: // convert volume slide down + case 9: // convert volume slide down track->command = 26; track->param1 = 0; break; } } } - } - else - { // version >= 5 - realloc_patterns (64, 64, 18); + } else { // version >= 5 + realloc_patterns(64, 64, 18); - for (i = 0; i < numpats; i++) - for (j = 0; j < 18; j++) - for (k = 0; k < 64; k++) - { + for(i=0;i<numpats;i++) + for(j=0;j<18;j++) + for(k=0;k<64;k++) { struct Tracks *track = &tracks[i * 18 + j][k]; - unsigned char *o = &org[i * 64 * t * 4 + j * 64 * 4 + k * 4]; + unsigned char *o = &org[i*64*t*4+j*64*4+k*4]; track->note = o[0] == 255 ? 127 : o[0]; track->inst = o[1]; @@ -304,16 +240,15 @@ Ca2mLoader::load (VFSFile & fd, const CFileProvider & fp) track->param2 = o[3] & 0x0f; // Convert '&' command - if (o[2] == 36) - switch (track->param1) - { - case 0: // pattern delay (frames) + if(o[2] == 36) + switch(track->param1) { + case 0: // pattern delay (frames) track->command = 29; track->param1 = 0; // param2 already set correctly break; - case 1: // pattern delay (rows) + case 1: // pattern delay (rows) track->command = 14; track->param1 = 8; // param2 already set correctly @@ -322,276 +257,228 @@ Ca2mLoader::load (VFSFile & fd, const CFileProvider & fp) } } - init_trackord (); + init_trackord(); - if (version == 1 || version == 5) - { - delete[]org; - } + if(version == 1 || version == 5) + delete [] org; else - { - delete[]secdata; - } + delete [] secdata; // Process flags - if (version >= 5) - { - CmodPlayer::flags |= Opl3; // All versions >= 5 are OPL3 - if (flags & 8) - CmodPlayer::flags |= Tremolo; // Tremolo depth - if (flags & 16) - CmodPlayer::flags |= Vibrato; // Vibrato depth + if(version >= 5) { + CmodPlayer::flags |= Opl3; // All versions >= 5 are OPL3 + if(flags & 8) CmodPlayer::flags |= Tremolo; // Tremolo depth + if(flags & 16) CmodPlayer::flags |= Vibrato; // Vibrato depth } - fp.close (f); - rewind (0); + fp.close(f); + rewind(0); return true; } -float -Ca2mLoader::getrefresh () +float Ca2mLoader::getrefresh() { - if (tempo != 18) - return (float) (tempo); - else - return 18.2f; + if(tempo != 18) + return (float) (tempo); + else + return 18.2f; } /*** private methods *************************************/ -void -Ca2mLoader::inittree () +void Ca2mLoader::inittree() { - unsigned short i; + unsigned short i; - for (i = 2; i <= TWICEMAX; i++) - { - dad[i] = i / 2; - freq[i] = 1; - } + for(i=2;i<=TWICEMAX;i++) { + dad[i] = i / 2; + freq[i] = 1; + } - for (i = 1; i <= MAXCODE; i++) - { - leftc[i] = 2 * i; - rghtc[i] = 2 * i + 1; - } + for(i=1;i<=MAXCHAR;i++) { + leftc[i] = 2 * i; + rghtc[i] = 2 * i + 1; + } } -void -Ca2mLoader::updatefreq (unsigned short a, unsigned short b) +void Ca2mLoader::updatefreq(unsigned short a,unsigned short b) { - do - { - freq[dad[a]] = freq[a] + freq[b]; - a = dad[a]; - if (a != ROOT) - { - if (leftc[dad[a]] == a) - b = rghtc[dad[a]]; - else - b = leftc[dad[a]]; - } - } while (a != ROOT); - - if (freq[ROOT] == MAXFREQ) - for (a = 1; a <= TWICEMAX; a++) - freq[a] >>= 1; + do { + freq[dad[a]] = freq[a] + freq[b]; + a = dad[a]; + if(a != ROOT) { + if(leftc[dad[a]] == a) + b = rghtc[dad[a]]; + else + b = leftc[dad[a]]; + } + } while(a != ROOT); + + if(freq[ROOT] == MAXFREQ) + for(a=1;a<=TWICEMAX;a++) + freq[a] >>= 1; } -void -Ca2mLoader::updatemodel (unsigned short code) +void Ca2mLoader::updatemodel(unsigned short code) { - unsigned short a = code + SUCCMAX, b, c, code1, code2; - - freq[a]++; - if (dad[a] != ROOT) - { - code1 = dad[a]; - if (leftc[code1] == a) - updatefreq (a, rghtc[code1]); - else - updatefreq (a, leftc[code1]); - - do - { - code2 = dad[code1]; - if (leftc[code2] == code1) - b = rghtc[code2]; - else - b = leftc[code2]; - - if (freq[a] > freq[b]) - { - if (leftc[code2] == code1) - rghtc[code2] = a; - else - leftc[code2] = a; - - if (leftc[code1] == a) - { - leftc[code1] = b; - c = rghtc[code1]; + unsigned short a=code+SUCCMAX,b,c,code1,code2; + + freq[a]++; + if(dad[a] != ROOT) { + code1 = dad[a]; + if(leftc[code1] == a) + updatefreq(a,rghtc[code1]); + else + updatefreq(a,leftc[code1]); + + do { + code2 = dad[code1]; + if(leftc[code2] == code1) + b = rghtc[code2]; + else + b = leftc[code2]; + + if(freq[a] > freq[b]) { + if(leftc[code2] == code1) + rghtc[code2] = a; + else + leftc[code2] = a; + + if(leftc[code1] == a) { + leftc[code1] = b; + c = rghtc[code1]; + } else { + rghtc[code1] = b; + c = leftc[code1]; + } + + dad[b] = code1; + dad[a] = code2; + updatefreq(b,c); + a = b; + } + + a = dad[a]; + code1 = dad[a]; + } while(code1 != ROOT); } - else - { - rghtc[code1] = b; - c = leftc[code1]; - } - - dad[b] = code1; - dad[a] = code2; - updatefreq (b, c); - a = b; - } - - a = dad[a]; - code1 = dad[a]; - } while (code1 != ROOT); - } } -unsigned short -Ca2mLoader::inputcode (unsigned short bits) +unsigned short Ca2mLoader::inputcode(unsigned short bits) { - unsigned short i, code = 0; - - for (i = 1; i <= bits; i++) - { - if (!ibitcount) - { - if (ibitcount == MAXBUF) - ibufcount = 0; - ibitbuffer = wdbuf[ibufcount]; - ibufcount++; - ibitcount = 15; - } - else - ibitcount--; - - if (ibitbuffer > 0x7fff) - code |= bitvalue[i - 1]; - ibitbuffer <<= 1; - } + unsigned short i,code=0; + + for(i=1;i<=bits;i++) { + if(!ibitcount) { + if(ibitcount == MAXBUF) + ibufcount = 0; + ibitbuffer = wdbuf[ibufcount]; + ibufcount++; + ibitcount = 15; + } else + ibitcount--; + + if(ibitbuffer > 0x7fff) + code |= bitvalue[i-1]; + ibitbuffer <<= 1; + } - return code; + return code; } -unsigned short -Ca2mLoader::uncompress () +unsigned short Ca2mLoader::uncompress() { - unsigned short a = 1; - - do - { - if (!ibitcount) - { - if (ibufcount == MAXBUF) - ibufcount = 0; - ibitbuffer = wdbuf[ibufcount]; - ibufcount++; - ibitcount = 15; - } - else - ibitcount--; - - if (ibitbuffer > 0x7fff) - a = rghtc[a]; - else - a = leftc[a]; - ibitbuffer <<= 1; - } while (a <= MAXCODE); - - a -= SUCCMAX; - updatemodel (a); - return a; + unsigned short a=1; + + do { + if(!ibitcount) { + if(ibufcount == MAXBUF) + ibufcount = 0; + ibitbuffer = wdbuf[ibufcount]; + ibufcount++; + ibitcount = 15; + } else + ibitcount--; + + if(ibitbuffer > 0x7fff) + a = rghtc[a]; + else + a = leftc[a]; + ibitbuffer <<= 1; + } while(a <= MAXCHAR); + + a -= SUCCMAX; + updatemodel(a); + return a; } -void -Ca2mLoader::decode () +void Ca2mLoader::decode() { - unsigned short i, j, k, t, c, count = 0, dist, len, index; - - inittree (); - c = uncompress (); - - while (c != TERMINATE) - { - if (c < 256) - { - obuf[obufcount] = (unsigned char) c; - obufcount++; - if (obufcount == MAXBUF) - { - output_size = MAXBUF; - obufcount = 0; - } - - buf[count] = (unsigned char) c; - count++; - if (count == MAXSIZE) - count = 0; - } - else - { - t = c - FIRSTCODE; - index = t / CODESPERRANGE; - len = t + MINCOPY - index * CODESPERRANGE; - dist = inputcode (copybits[index]) + len + copymin[index]; - - j = count; - k = count - dist; - if (count < dist) - k += MAXSIZE; - - for (i = 0; i <= len - 1; i++) - { - obuf[obufcount] = buf[k]; - obufcount++; - if (obufcount == MAXBUF) - { - output_size = MAXBUF; - obufcount = 0; + unsigned short i,j,k,t,c,count=0,dist,len,index; + + inittree(); + c = uncompress(); + + while(c != TERMINATE) { + if(c < 256) { + obuf[obufcount] = (unsigned char)c; + obufcount++; + if(obufcount == MAXBUF) { + output_size = MAXBUF; + obufcount = 0; + } + + buf[count] = (unsigned char)c; + count++; + if(count == MAXSIZE) + count = 0; + } else { + t = c - FIRSTCODE; + index = t / CODESPERRANGE; + len = t + MINCOPY - index * CODESPERRANGE; + dist = inputcode(copybits[index]) + len + copymin[index]; + + j = count; + k = count - dist; + if(count < dist) + k += MAXSIZE; + + for(i=0;i<=len-1;i++) { + obuf[obufcount] = buf[k]; + obufcount++; + if(obufcount == MAXBUF) { + output_size = MAXBUF; + obufcount = 0; + } + + buf[j] = buf[k]; + j++; k++; + if(j == MAXSIZE) j = 0; + if(k == MAXSIZE) k = 0; + } + + count += len; + if(count >= MAXSIZE) + count -= MAXSIZE; + } + c = uncompress(); } - - buf[j] = buf[k]; - j++; - k++; - if (j == MAXSIZE) - j = 0; - if (k == MAXSIZE) - k = 0; - } - - count += len; - if (count >= MAXSIZE) - count -= MAXSIZE; - } - c = uncompress (); - } - output_size = obufcount; + output_size = obufcount; } -unsigned short -Ca2mLoader::sixdepak (unsigned short *source, unsigned char *dest, - unsigned short size) +unsigned short Ca2mLoader::sixdepak(unsigned short *source, unsigned char *dest, + unsigned short size) { - if ((unsigned int) size + 4096 > MAXBUF) - return 0; - - buf = new unsigned char[MAXSIZE]; - input_size = size; - ibitcount = 0; - ibitbuffer = 0; - obufcount = 0; - ibufcount = 0; - wdbuf = source; - obuf = dest; - - decode (); - if (buf) - { - delete[]buf; - buf = 0; - } - return output_size; + if((unsigned int)size + 4096 > MAXBUF) + return 0; + + buf = new unsigned char [MAXSIZE]; + input_size = size; + ibitcount = 0; ibitbuffer = 0; + obufcount = 0; ibufcount = 0; + wdbuf = source; obuf = dest; + + decode(); + delete [] buf; + return output_size; } diff --git a/src/adplug/core/a2m.h b/src/adplug/core/a2m.h index d55ae13..7867d85 100644 --- a/src/adplug/core/a2m.h +++ b/src/adplug/core/a2m.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -29,56 +29,55 @@ class Ca2mLoader: public CmodPlayer public: static CPlayer *factory(Copl *newopl); - Ca2mLoader(Copl *newopl) - : CmodPlayer(newopl) - { }; + Ca2mLoader(Copl *newopl): CmodPlayer(newopl) + { } - bool load(VFSFile &fd, const CFileProvider &fp); - float getrefresh(); + bool load(const std::string &filename, const CFileProvider &fp); + float getrefresh(); - std::string gettype() - { return std::string("AdLib Tracker 2"); }; - std::string gettitle() - { if(*songname) return std::string(songname,1,*songname); else return std::string(); }; - std::string getauthor() - { if(*author) return std::string(author,1,*author); else return std::string(); }; - unsigned int getinstruments() - { return 250; }; - std::string getinstrument(unsigned int n) - { return std::string(instname[n],1,*instname[n]); }; + std::string gettype() + { return std::string("AdLib Tracker 2"); } + std::string gettitle() + { if(*songname) return std::string(songname,1,*songname); else return std::string(); } + std::string getauthor() + { if(*author) return std::string(author,1,*author); else return std::string(); } + unsigned int getinstruments() + { return 250; } + std::string getinstrument(unsigned int n) + { return std::string(instname[n],1,*instname[n]); } private: -#define ADPLUG_A2M_COPYRANGES 6 -#define ADPLUG_A2M_FIRSTCODE 257 -#define ADPLUG_A2M_MINCOPY 3 -#define ADPLUG_A2M_MAXCOPY 255 -#define ADPLUG_A2M_CODESPERRANGE (ADPLUG_A2M_MAXCOPY - ADPLUG_A2M_MINCOPY + 1) -#define ADPLUG_A2M_MAXCHAR (ADPLUG_A2M_FIRSTCODE + \ - ADPLUG_A2M_COPYRANGES * ADPLUG_A2M_CODESPERRANGE - 1) -#define ADPLUG_A2M_TWICEMAX (2 * ADPLUG_A2M_MAXCHAR + 1) +#define ADPLUG_A2M_COPYRANGES 6 +#define ADPLUG_A2M_FIRSTCODE 257 +#define ADPLUG_A2M_MINCOPY 3 +#define ADPLUG_A2M_MAXCOPY 255 +#define ADPLUG_A2M_CODESPERRANGE (ADPLUG_A2M_MAXCOPY - ADPLUG_A2M_MINCOPY + 1) +#define ADPLUG_A2M_MAXCHAR (ADPLUG_A2M_FIRSTCODE + ADPLUG_A2M_COPYRANGES * ADPLUG_A2M_CODESPERRANGE - 1) +#define ADPLUG_A2M_TWICEMAX (2 * ADPLUG_A2M_MAXCHAR + 1) - static const unsigned int MAXFREQ, MINCOPY, MAXCOPY, COPYRANGES, - CODESPERRANGE, TERMINATE, FIRSTCODE, MAXCODE, SUCCMAX, TWICEMAX, ROOT, - MAXBUF, MAXDISTANCE, MAXSIZE; + static const unsigned int MAXFREQ, MINCOPY, MAXCOPY, COPYRANGES, + CODESPERRANGE, TERMINATE, FIRSTCODE, MAXCHAR, SUCCMAX, TWICEMAX, ROOT, + MAXBUF, MAXDISTANCE, MAXSIZE; - static const unsigned short bitvalue[14]; - static const signed short copybits[ADPLUG_A2M_COPYRANGES], - copymin[ADPLUG_A2M_COPYRANGES]; + static const unsigned short bitvalue[14]; + static const signed short copybits[ADPLUG_A2M_COPYRANGES], + copymin[ADPLUG_A2M_COPYRANGES]; - void inittree(); - void updatefreq(unsigned short a,unsigned short b); - void updatemodel(unsigned short code); - unsigned short inputcode(unsigned short bits); - unsigned short uncompress(); - void decode(); - unsigned short sixdepak(unsigned short *source,unsigned char *dest,unsigned short size); + void inittree(); + void updatefreq(unsigned short a,unsigned short b); + void updatemodel(unsigned short code); + unsigned short inputcode(unsigned short bits); + unsigned short uncompress(); + void decode(); + unsigned short sixdepak(unsigned short *source,unsigned char *dest,unsigned short size); - char songname[43], author[43], instname[250][33]; + char songname[43], author[43], instname[250][33]; - unsigned short ibitcount, ibitbuffer, ibufcount, obufcount, input_size, - output_size, leftc[ADPLUG_A2M_MAXCHAR+1], rghtc[ADPLUG_A2M_MAXCHAR+1], - dad[ADPLUG_A2M_TWICEMAX+1], freq[ADPLUG_A2M_TWICEMAX+1], *wdbuf; - unsigned char *obuf, *buf; + unsigned short ibitcount, ibitbuffer, ibufcount, obufcount, input_size, + output_size, leftc[ADPLUG_A2M_MAXCHAR+1], rghtc[ADPLUG_A2M_MAXCHAR+1], + dad[ADPLUG_A2M_TWICEMAX+1], freq[ADPLUG_A2M_TWICEMAX+1], *wdbuf; + unsigned char *obuf, *buf; }; + #endif diff --git a/src/adplug/core/adl.cc b/src/adplug/core/adl.cc index 281c3b1..18b3ae8 100644 --- a/src/adplug/core/adl.cc +++ b/src/adplug/core/adl.cc @@ -43,32 +43,33 @@ * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + * $URL: https://svn.sourceforge.net/svnroot/scummvm/scummvm/trunk/engines/kyra/sound_adlib.cpp $ + * $Id: adl.cpp,v 1.11 2008/02/11 20:18:27 dynamite Exp $ + * */ -#include <assert.h> +#include <cstring> #include <inttypes.h> #include <stdarg.h> -#include <string.h> +#include <assert.h> #include "adl.h" #include "debug.h" #ifdef ADL_DEBUG -# define warning(...) AdPlug_LogWrite(__VA_ARGS__); \ +# define warning(...) AdPlug_LogWrite(__VA_ARGS__); \ AdPlug_LogWrite("\n") -# define debugC(i1, i2, ...) AdPlug_LogWrite(__VA_ARGS__); \ +# define debugC(i1, i2, ...) AdPlug_LogWrite(__VA_ARGS__); \ AdPlug_LogWrite("\n") #else -# define kDebugLevelSound 1 +# define kDebugLevelSound 1 -static inline void -warning (const char *str, ...) +static inline void warning(const char *str, ...) { } -static inline void -debugC (int i1, int i2, const char *str, ...) +static inline void debugC(int i1, int i2, const char *str, ...) { } #endif @@ -84,99 +85,87 @@ debugC (int i1, int i2, const char *str, ...) #define CALLBACKS_PER_SECOND 72 typedef uint8_t uint8; -typedef int8_t int8; -typedef uint16_t uint16; +typedef int8_t int8; +typedef uint16_t uint16; typedef int16_t int16; -typedef uint32_t uint32; +typedef uint32_t uint32; typedef int32_t int32; typedef uint8_t byte; -static inline uint16 -READ_LE_UINT16 (const void *ptr) -{ - const byte *b = (const byte *) ptr; +static inline uint16 READ_LE_UINT16(const void *ptr) { + const byte *b = (const byte *)ptr; return (b[1] << 8) + b[0]; } -static inline uint16 -READ_BE_UINT16 (const void *ptr) -{ - const byte *b = (const byte *) ptr; +static inline uint16 READ_BE_UINT16(const void *ptr) { + const byte *b = (const byte *)ptr; return (b[0] << 8) + b[1]; } -class AdlibDriver -{ +class AdlibDriver { public: - AdlibDriver (Copl * opl); - ~AdlibDriver (); + AdlibDriver(Copl *opl); + ~AdlibDriver(); - int callback (int opcode, ...); - void callback (); + int callback(int opcode, ...); + void callback(); // AudioStream API // int readBuffer(int16 *buffer, const int numSamples) { - // int32 samplesLeft = numSamples; - // memset(buffer, 0, sizeof(int16) * numSamples); - // while (samplesLeft) { - // if (!_samplesTillCallback) { - // callback(); - // _samplesTillCallback = _samplesPerCallback; - // _samplesTillCallbackRemainder += _samplesPerCallbackRemainder; - // if (_samplesTillCallbackRemainder >= CALLBACKS_PER_SECOND) { - // _samplesTillCallback++; - // _samplesTillCallbackRemainder -= CALLBACKS_PER_SECOND; - // } + // int32 samplesLeft = numSamples; + // memset(buffer, 0, sizeof(int16) * numSamples); + // while (samplesLeft) { + // if (!_samplesTillCallback) { + // callback(); + // _samplesTillCallback = _samplesPerCallback; + // _samplesTillCallbackRemainder += _samplesPerCallbackRemainder; + // if (_samplesTillCallbackRemainder >= CALLBACKS_PER_SECOND) { + // _samplesTillCallback++; + // _samplesTillCallbackRemainder -= CALLBACKS_PER_SECOND; + // } + // } + + // int32 render = MIN(samplesLeft, _samplesTillCallback); + // samplesLeft -= render; + // _samplesTillCallback -= render; + // YM3812UpdateOne(_adlib, buffer, render); + // buffer += render; // } - - // int32 render = MIN(samplesLeft, _samplesTillCallback); - // samplesLeft -= render; - // _samplesTillCallback -= render; - // YM3812UpdateOne(_adlib, buffer, render); - // buffer += render; - // } - // return numSamples; + // return numSamples; // } - bool isStereo () const - { - return false; - } - bool endOfData () const - { - return false; - } + bool isStereo() const { return false; } + bool endOfData() const { return false; } // int getRate() const { return _mixer->getOutputRate(); } - struct OpcodeEntry - { - typedef int (AdlibDriver::*DriverOpcode) (va_list & list); + struct OpcodeEntry { + typedef int (AdlibDriver::*DriverOpcode)(va_list &list); DriverOpcode function; const char *name; }; - void setupOpcodeList (); + void setupOpcodeList(); const OpcodeEntry *_opcodeList; int _opcodesEntries; - int snd_ret0x100 (va_list & list); - int snd_ret0x1983 (va_list & list); - int snd_initDriver (va_list & list); - int snd_deinitDriver (va_list & list); - int snd_setSoundData (va_list & list); - int snd_unkOpcode1 (va_list & list); - int snd_startSong (va_list & list); - int snd_unkOpcode2 (va_list & list); - int snd_unkOpcode3 (va_list & list); - int snd_readByte (va_list & list); - int snd_writeByte (va_list & list); - int snd_getSoundTrigger (va_list & list); - int snd_unkOpcode4 (va_list & list); - int snd_dummy (va_list & list); - int snd_getNullvar4 (va_list & list); - int snd_setNullvar3 (va_list & list); - int snd_setFlag (va_list & list); - int snd_clearFlag (va_list & list); + int snd_ret0x100(va_list &list); + int snd_ret0x1983(va_list &list); + int snd_initDriver(va_list &list); + int snd_deinitDriver(va_list &list); + int snd_setSoundData(va_list &list); + int snd_unkOpcode1(va_list &list); + int snd_startSong(va_list &list); + int snd_unkOpcode2(va_list &list); + int snd_unkOpcode3(va_list &list); + int snd_readByte(va_list &list); + int snd_writeByte(va_list &list); + int snd_getSoundTrigger(va_list &list); + int snd_unkOpcode4(va_list &list); + int snd_dummy(va_list &list); + int snd_getNullvar4(va_list &list); + int snd_setNullvar3(va_list &list); + int snd_setFlag(va_list &list); + int snd_clearFlag(va_list &list); // These variables have not yet been named, but some of them are partly // known nevertheless: @@ -201,8 +190,7 @@ public: // unk40 - Currently unused, except for updateCallback56() // unk41 - Sound-effect. Used for primaryEffect2() - struct Channel - { + struct Channel { uint8 opExtraLevel2; uint8 *dataptr; uint8 duration; @@ -230,7 +218,7 @@ public: uint8 position; uint8 regAx; uint8 regBx; - typedef void (AdlibDriver::*Callback) (Channel &); + typedef void (AdlibDriver::*Callback)(Channel&); Callback primaryEffect; Callback secondaryEffect; uint8 fractionalSpacing; @@ -253,30 +241,29 @@ public: int8 unk16; }; - void primaryEffect1 (Channel & channel); - void primaryEffect2 (Channel & channel); - void secondaryEffect1 (Channel & channel); + void primaryEffect1(Channel &channel); + void primaryEffect2(Channel &channel); + void secondaryEffect1(Channel &channel); - void resetAdlibState (); - void writeOPL (byte reg, byte val); - void initChannel (Channel & channel); - void noteOff (Channel & channel); - void unkOutput2 (uint8 num); + void resetAdlibState(); + void writeOPL(byte reg, byte val); + void initChannel(Channel &channel); + void noteOff(Channel &channel); + void unkOutput2(uint8 num); - uint16 getRandomNr (); - void setupDuration (uint8 duration, Channel & channel); + uint16 getRandomNr(); + void setupDuration(uint8 duration, Channel &channel); - void setupNote (uint8 rawNote, Channel & channel, bool flag = false); - void setupInstrument (uint8 regOffset, uint8 * dataptr, Channel & channel); - void noteOn (Channel & channel); + void setupNote(uint8 rawNote, Channel &channel, bool flag = false); + void setupInstrument(uint8 regOffset, uint8 *dataptr, Channel &channel); + void noteOn(Channel &channel); - void adjustVolume (Channel & channel); + void adjustVolume(Channel &channel); - uint8 calculateOpLevel1 (Channel & channel); - uint8 calculateOpLevel2 (Channel & channel); + uint8 calculateOpLevel1(Channel &channel); + uint8 calculateOpLevel2(Channel &channel); - uint16 checkValue (int16 val) - { + uint16 checkValue(int16 val) { if (val < 0) val = 0; else if (val > 0x3F) @@ -289,115 +276,83 @@ public: // * One for programs, starting at offset 0. // * One for instruments, starting at offset 500. - uint8 *getProgram (int progId) - { - return _soundData + READ_LE_UINT16 (_soundData + 2 * progId); + uint8 *getProgram(int progId) { + return _soundData + READ_LE_UINT16(_soundData + 2 * progId); } - uint8 *getInstrument (int instrumentId) - { - return _soundData + READ_LE_UINT16 (_soundData + 500 + 2 * instrumentId); + uint8 *getInstrument(int instrumentId) { + return _soundData + READ_LE_UINT16(_soundData + 500 + 2 * instrumentId); } - void setupPrograms (); - void executePrograms (); + void setupPrograms(); + void executePrograms(); - struct ParserOpcode - { - typedef int (AdlibDriver::*POpcode) (uint8 * &dataptr, Channel & channel, - uint8 value); + struct ParserOpcode { + typedef int (AdlibDriver::*POpcode)(uint8 *&dataptr, Channel &channel, uint8 value); POpcode function; const char *name; }; - void setupParserOpcodeTable (); + void setupParserOpcodeTable(); const ParserOpcode *_parserOpcodeTable; int _parserOpcodeTableSize; - int update_setRepeat (uint8 * &dataptr, Channel & channel, uint8 value); - int update_checkRepeat (uint8 * &dataptr, Channel & channel, uint8 value); - int update_setupProgram (uint8 * &dataptr, Channel & channel, uint8 value); - int update_setNoteSpacing (uint8 * &dataptr, Channel & channel, - uint8 value); - int update_jump (uint8 * &dataptr, Channel & channel, uint8 value); - int update_jumpToSubroutine (uint8 * &dataptr, Channel & channel, - uint8 value); - int update_returnFromSubroutine (uint8 * &dataptr, Channel & channel, - uint8 value); - int update_setBaseOctave (uint8 * &dataptr, Channel & channel, uint8 value); - int update_stopChannel (uint8 * &dataptr, Channel & channel, uint8 value); - int update_playRest (uint8 * &dataptr, Channel & channel, uint8 value); - int update_writeAdlib (uint8 * &dataptr, Channel & channel, uint8 value); - int update_setupNoteAndDuration (uint8 * &dataptr, Channel & channel, - uint8 value); - int update_setBaseNote (uint8 * &dataptr, Channel & channel, uint8 value); - int update_setupSecondaryEffect1 (uint8 * &dataptr, Channel & channel, - uint8 value); - int update_stopOtherChannel (uint8 * &dataptr, Channel & channel, - uint8 value); - int update_waitForEndOfProgram (uint8 * &dataptr, Channel & channel, - uint8 value); - int update_setupInstrument (uint8 * &dataptr, Channel & channel, - uint8 value); - int update_setupPrimaryEffect1 (uint8 * &dataptr, Channel & channel, - uint8 value); - int update_removePrimaryEffect1 (uint8 * &dataptr, Channel & channel, - uint8 value); - int update_setBaseFreq (uint8 * &dataptr, Channel & channel, uint8 value); - int update_setupPrimaryEffect2 (uint8 * &dataptr, Channel & channel, - uint8 value); - int update_setPriority (uint8 * &dataptr, Channel & channel, uint8 value); - int updateCallback23 (uint8 * &dataptr, Channel & channel, uint8 value); - int updateCallback24 (uint8 * &dataptr, Channel & channel, uint8 value); - int update_setExtraLevel1 (uint8 * &dataptr, Channel & channel, - uint8 value); - int update_setupDuration (uint8 * &dataptr, Channel & channel, uint8 value); - int update_playNote (uint8 * &dataptr, Channel & channel, uint8 value); - int update_setFractionalNoteSpacing (uint8 * &dataptr, Channel & channel, - uint8 value); - int update_setTempo (uint8 * &dataptr, Channel & channel, uint8 value); - int update_removeSecondaryEffect1 (uint8 * &dataptr, Channel & channel, - uint8 value); - int update_setChannelTempo (uint8 * &dataptr, Channel & channel, - uint8 value); - int update_setExtraLevel3 (uint8 * &dataptr, Channel & channel, - uint8 value); - int update_setExtraLevel2 (uint8 * &dataptr, Channel & channel, - uint8 value); - int update_changeExtraLevel2 (uint8 * &dataptr, Channel & channel, - uint8 value); - int update_setAMDepth (uint8 * &dataptr, Channel & channel, uint8 value); - int update_setVibratoDepth (uint8 * &dataptr, Channel & channel, - uint8 value); - int update_changeExtraLevel1 (uint8 * &dataptr, Channel & channel, - uint8 value); - int updateCallback38 (uint8 * &dataptr, Channel & channel, uint8 value); - int updateCallback39 (uint8 * &dataptr, Channel & channel, uint8 value); - int update_removePrimaryEffect2 (uint8 * &dataptr, Channel & channel, - uint8 value); - int updateCallback41 (uint8 * &dataptr, Channel & channel, uint8 value); - int update_resetToGlobalTempo (uint8 * &dataptr, Channel & channel, - uint8 value); - int update_nop1 (uint8 * &dataptr, Channel & channel, uint8 value); - int update_setDurationRandomness (uint8 * &dataptr, Channel & channel, - uint8 value); - int update_changeChannelTempo (uint8 * &dataptr, Channel & channel, - uint8 value); - int updateCallback46 (uint8 * &dataptr, Channel & channel, uint8 value); - int update_nop2 (uint8 * &dataptr, Channel & channel, uint8 value); - int update_setupRhythmSection (uint8 * &dataptr, Channel & channel, - uint8 value); - int update_playRhythmSection (uint8 * &dataptr, Channel & channel, - uint8 value); - int update_removeRhythmSection (uint8 * &dataptr, Channel & channel, - uint8 value); - int updateCallback51 (uint8 * &dataptr, Channel & channel, uint8 value); - int updateCallback52 (uint8 * &dataptr, Channel & channel, uint8 value); - int updateCallback53 (uint8 * &dataptr, Channel & channel, uint8 value); - int update_setSoundTrigger (uint8 * &dataptr, Channel & channel, - uint8 value); - int update_setTempoReset (uint8 * &dataptr, Channel & channel, uint8 value); - int updateCallback56 (uint8 * &dataptr, Channel & channel, uint8 value); + int update_setRepeat(uint8 *&dataptr, Channel &channel, uint8 value); + int update_checkRepeat(uint8 *&dataptr, Channel &channel, uint8 value); + int update_setupProgram(uint8 *&dataptr, Channel &channel, uint8 value); + int update_setNoteSpacing(uint8 *&dataptr, Channel &channel, uint8 value); + int update_jump(uint8 *&dataptr, Channel &channel, uint8 value); + int update_jumpToSubroutine(uint8 *&dataptr, Channel &channel, uint8 value); + int update_returnFromSubroutine(uint8 *&dataptr, Channel &channel, uint8 value); + int update_setBaseOctave(uint8 *&dataptr, Channel &channel, uint8 value); + int update_stopChannel(uint8 *&dataptr, Channel &channel, uint8 value); + int update_playRest(uint8 *&dataptr, Channel &channel, uint8 value); + int update_writeAdlib(uint8 *&dataptr, Channel &channel, uint8 value); + int update_setupNoteAndDuration(uint8 *&dataptr, Channel &channel, uint8 value); + int update_setBaseNote(uint8 *&dataptr, Channel &channel, uint8 value); + int update_setupSecondaryEffect1(uint8 *&dataptr, Channel &channel, uint8 value); + int update_stopOtherChannel(uint8 *&dataptr, Channel &channel, uint8 value); + int update_waitForEndOfProgram(uint8 *&dataptr, Channel &channel, uint8 value); + int update_setupInstrument(uint8 *&dataptr, Channel &channel, uint8 value); + int update_setupPrimaryEffect1(uint8 *&dataptr, Channel &channel, uint8 value); + int update_removePrimaryEffect1(uint8 *&dataptr, Channel &channel, uint8 value); + int update_setBaseFreq(uint8 *&dataptr, Channel &channel, uint8 value); + int update_setupPrimaryEffect2(uint8 *&dataptr, Channel &channel, uint8 value); + int update_setPriority(uint8 *&dataptr, Channel &channel, uint8 value); + int updateCallback23(uint8 *&dataptr, Channel &channel, uint8 value); + int updateCallback24(uint8 *&dataptr, Channel &channel, uint8 value); + int update_setExtraLevel1(uint8 *&dataptr, Channel &channel, uint8 value); + int update_setupDuration(uint8 *&dataptr, Channel &channel, uint8 value); + int update_playNote(uint8 *&dataptr, Channel &channel, uint8 value); + int update_setFractionalNoteSpacing(uint8 *&dataptr, Channel &channel, uint8 value); + int update_setTempo(uint8 *&dataptr, Channel &channel, uint8 value); + int update_removeSecondaryEffect1(uint8 *&dataptr, Channel &channel, uint8 value); + int update_setChannelTempo(uint8 *&dataptr, Channel &channel, uint8 value); + int update_setExtraLevel3(uint8 *&dataptr, Channel &channel, uint8 value); + int update_setExtraLevel2(uint8 *&dataptr, Channel &channel, uint8 value); + int update_changeExtraLevel2(uint8 *&dataptr, Channel &channel, uint8 value); + int update_setAMDepth(uint8 *&dataptr, Channel &channel, uint8 value); + int update_setVibratoDepth(uint8 *&dataptr, Channel &channel, uint8 value); + int update_changeExtraLevel1(uint8 *&dataptr, Channel &channel, uint8 value); + int updateCallback38(uint8 *&dataptr, Channel &channel, uint8 value); + int updateCallback39(uint8 *&dataptr, Channel &channel, uint8 value); + int update_removePrimaryEffect2(uint8 *&dataptr, Channel &channel, uint8 value); + int updateCallback41(uint8 *&dataptr, Channel &channel, uint8 value); + int update_resetToGlobalTempo(uint8 *&dataptr, Channel &channel, uint8 value); + int update_nop1(uint8 *&dataptr, Channel &channel, uint8 value); + int update_setDurationRandomness(uint8 *&dataptr, Channel &channel, uint8 value); + int update_changeChannelTempo(uint8 *&dataptr, Channel &channel, uint8 value); + int updateCallback46(uint8 *&dataptr, Channel &channel, uint8 value); + int update_nop2(uint8 *&dataptr, Channel &channel, uint8 value); + int update_setupRhythmSection(uint8 *&dataptr, Channel &channel, uint8 value); + int update_playRhythmSection(uint8 *&dataptr, Channel &channel, uint8 value); + int update_removeRhythmSection(uint8 *&dataptr, Channel &channel, uint8 value); + int updateCallback51(uint8 *&dataptr, Channel &channel, uint8 value); + int updateCallback52(uint8 *&dataptr, Channel &channel, uint8 value); + int updateCallback53(uint8 *&dataptr, Channel &channel, uint8 value); + int update_setSoundTrigger(uint8 *&dataptr, Channel &channel, uint8 value); + int update_setTempoReset(uint8 *&dataptr, Channel &channel, uint8 value); + int updateCallback56(uint8 *&dataptr, Channel &channel, uint8 value); // These variables have not yet been named, but some of them are partly // known nevertheless: @@ -489,10 +444,11 @@ public: Copl *opl; }; -AdlibDriver::AdlibDriver (Copl * newopl):opl (newopl) +AdlibDriver::AdlibDriver(Copl *newopl) + : opl(newopl) { - setupOpcodeList (); - setupParserOpcodeTable (); + setupOpcodeList(); + setupParserOpcodeTable(); // _mixer = mixer; @@ -500,7 +456,7 @@ AdlibDriver::AdlibDriver (Copl * newopl):opl (newopl) // _adlib = makeAdlibOPL(getRate()); // assert(_adlib); - memset (_channels, 0, sizeof (_channels)); + memset(_channels, 0, sizeof(_channels)); _soundData = 0; _vibratoAndAMDepthBits = _curRegOffset = 0; @@ -528,101 +484,77 @@ AdlibDriver::AdlibDriver (Copl * newopl):opl (newopl) _samplesTillCallbackRemainder = 0; } -AdlibDriver::~AdlibDriver () -{ +AdlibDriver::~AdlibDriver() { // _mixer->setupPremix(0); // OPLDestroy(_adlib); // _adlib = 0; } -int -AdlibDriver::callback (int opcode, ...) -{ +int AdlibDriver::callback(int opcode, ...) { // lock(); - if (opcode >= _opcodesEntries || opcode < 0) - { - warning ("AdlibDriver: calling unknown opcode '%d'", opcode); + if (opcode >= _opcodesEntries || opcode < 0) { + warning("AdlibDriver: calling unknown opcode '%d'", opcode); return 0; } - debugC (9, kDebugLevelSound, "Calling opcode '%s' (%d)", - _opcodeList[opcode].name, opcode); + debugC(9, kDebugLevelSound, "Calling opcode '%s' (%d)", _opcodeList[opcode].name, opcode); va_list args; - va_start (args, opcode); - int returnValue = (this->*(_opcodeList[opcode].function)) (args); - va_end (args); + va_start(args, opcode); + int returnValue = (this->*(_opcodeList[opcode].function))(args); + va_end(args); // unlock(); return returnValue; } // Opcodes -int -AdlibDriver::snd_ret0x100 (va_list & list) -{ +int AdlibDriver::snd_ret0x100(va_list &list) { return 0x100; } -int -AdlibDriver::snd_ret0x1983 (va_list & list) -{ +int AdlibDriver::snd_ret0x1983(va_list &list) { return 0x1983; } -int -AdlibDriver::snd_initDriver (va_list & list) -{ +int AdlibDriver::snd_initDriver(va_list &list) { _lastProcessed = _soundsPlaying = 0; - resetAdlibState (); + resetAdlibState(); return 0; } -int -AdlibDriver::snd_deinitDriver (va_list & list) -{ - resetAdlibState (); +int AdlibDriver::snd_deinitDriver(va_list &list) { + resetAdlibState(); return 0; } -int -AdlibDriver::snd_setSoundData (va_list & list) -{ - if (_soundData) - { - delete[]_soundData; +int AdlibDriver::snd_setSoundData(va_list &list) { + if (_soundData) { + delete [] _soundData; _soundData = 0; } - _soundData = va_arg (list, uint8 *); + _soundData = va_arg(list, uint8*); return 0; } -int -AdlibDriver::snd_unkOpcode1 (va_list & list) -{ - warning ("unimplemented snd_unkOpcode1"); +int AdlibDriver::snd_unkOpcode1(va_list &list) { + warning("unimplemented snd_unkOpcode1"); return 0; } -int -AdlibDriver::snd_startSong (va_list & list) -{ - int songId = va_arg (list, int); +int AdlibDriver::snd_startSong(va_list &list) { + int songId = va_arg(list, int); _flags |= 8; _flagTrigger = 1; - uint8 *ptr = getProgram (songId); + uint8 *ptr = getProgram(songId); uint8 chan = *ptr; - if ((songId << 1) != 0) - { - if (chan == 9) - { + if ((songId << 1) != 0) { + if (chan == 9) { if (_flags & 2) return 0; - } - else - { + } else { if (_flags & 1) return 0; } @@ -634,35 +566,28 @@ AdlibDriver::snd_startSong (va_list & list) return 0; } -int -AdlibDriver::snd_unkOpcode2 (va_list & list) -{ - warning ("unimplemented snd_unkOpcode2"); +int AdlibDriver::snd_unkOpcode2(va_list &list) { + warning("unimplemented snd_unkOpcode2"); return 0; } -int -AdlibDriver::snd_unkOpcode3 (va_list & list) -{ - int value = va_arg (list, int); +int AdlibDriver::snd_unkOpcode3(va_list &list) { + int value = va_arg(list, int); int loop = value; - if (value < 0) - { + if (value < 0) { value = 0; loop = 9; } loop -= value; ++loop; - while (loop--) - { + while (loop--) { _curChannel = value; - Channel & channel = _channels[_curChannel]; + Channel &channel = _channels[_curChannel]; channel.priority = 0; channel.dataptr = 0; - if (value != 9) - { - noteOff (channel); + if (value != 9) { + noteOff(channel); } ++value; } @@ -670,94 +595,72 @@ AdlibDriver::snd_unkOpcode3 (va_list & list) return 0; } -int -AdlibDriver::snd_readByte (va_list & list) -{ - int a = va_arg (list, int); - int b = va_arg (list, int); - uint8 *ptr = getProgram (a) + b; +int AdlibDriver::snd_readByte(va_list &list) { + int a = va_arg(list, int); + int b = va_arg(list, int); + uint8 *ptr = getProgram(a) + b; return *ptr; } -int -AdlibDriver::snd_writeByte (va_list & list) -{ - int a = va_arg (list, int); - int b = va_arg (list, int); - int c = va_arg (list, int); - uint8 *ptr = getProgram (a) + b; +int AdlibDriver::snd_writeByte(va_list &list) { + int a = va_arg(list, int); + int b = va_arg(list, int); + int c = va_arg(list, int); + uint8 *ptr = getProgram(a) + b; uint8 oldValue = *ptr; - *ptr = (uint8) c; + *ptr = (uint8)c; return oldValue; } -int -AdlibDriver::snd_getSoundTrigger (va_list & list) -{ +int AdlibDriver::snd_getSoundTrigger(va_list &list) { return _soundTrigger; } -int -AdlibDriver::snd_unkOpcode4 (va_list & list) -{ - warning ("unimplemented snd_unkOpcode4"); +int AdlibDriver::snd_unkOpcode4(va_list &list) { + warning("unimplemented snd_unkOpcode4"); return 0; } -int -AdlibDriver::snd_dummy (va_list & list) -{ +int AdlibDriver::snd_dummy(va_list &list) { return 0; } -int -AdlibDriver::snd_getNullvar4 (va_list & list) -{ - warning ("unimplemented snd_getNullvar4"); +int AdlibDriver::snd_getNullvar4(va_list &list) { + warning("unimplemented snd_getNullvar4"); return 0; } -int -AdlibDriver::snd_setNullvar3 (va_list & list) -{ - warning ("unimplemented snd_setNullvar3"); +int AdlibDriver::snd_setNullvar3(va_list &list) { + warning("unimplemented snd_setNullvar3"); return 0; } -int -AdlibDriver::snd_setFlag (va_list & list) -{ +int AdlibDriver::snd_setFlag(va_list &list) { int oldFlags = _flags; - _flags |= va_arg (list, int); + _flags |= va_arg(list, int); return oldFlags; } -int -AdlibDriver::snd_clearFlag (va_list & list) -{ +int AdlibDriver::snd_clearFlag(va_list &list) { int oldFlags = _flags; - _flags &= ~(va_arg (list, int)); + _flags &= ~(va_arg(list, int)); return oldFlags; } // timer callback -void -AdlibDriver::callback () -{ +void AdlibDriver::callback() { // lock(); --_flagTrigger; if (_flagTrigger < 0) _flags &= ~8; - setupPrograms (); - executePrograms (); + setupPrograms(); + executePrograms(); uint8 temp = _unkValue3; _unkValue3 += _tempo; - if (_unkValue3 < temp) - { - if (!(--_unkValue2)) - { + if (_unkValue3 < temp) { + if (!(--_unkValue2)) { _unkValue2 = _unkValue1; ++_unkValue4; } @@ -765,29 +668,25 @@ AdlibDriver::callback () // unlock(); } -void -AdlibDriver::setupPrograms () -{ - while (_lastProcessed != _soundsPlaying) - { - uint8 *ptr = getProgram (_soundIdTable[_lastProcessed]); +void AdlibDriver::setupPrograms() { + while (_lastProcessed != _soundsPlaying) { + uint8 *ptr = getProgram(_soundIdTable[_lastProcessed]); uint8 chan = *ptr++; uint8 priority = *ptr++; // Only start this sound if its priority is higher than the one // already playing. - Channel & channel = _channels[chan]; + Channel &channel = _channels[chan]; - if (priority >= channel.priority) - { - initChannel (channel); + if (priority >= channel.priority) { + initChannel(channel); channel.priority = priority; channel.dataptr = ptr; channel.tempo = 0xFF; channel.position = 0xFF; channel.duration = 1; - unkOutput2 (chan); + unkOutput2(chan); } ++_lastProcessed; @@ -829,43 +728,34 @@ AdlibDriver::setupPrograms () // effects callbacks. The final opcode in a set can prevent this, if it's a // function and it returns anything other than 1. -void -AdlibDriver::executePrograms () -{ +void AdlibDriver::executePrograms() { // Each channel runs its own program. There are ten channels: One for // each Adlib channel (0-8), plus one "control channel" (9) which is // the one that tells the other channels what to do. - for (_curChannel = 9; _curChannel >= 0; --_curChannel) - { + for (_curChannel = 9; _curChannel >= 0; --_curChannel) { int result = 1; - if (!_channels[_curChannel].dataptr) - { + if (!_channels[_curChannel].dataptr) { continue; } - Channel & channel = _channels[_curChannel]; + Channel &channel = _channels[_curChannel]; _curRegOffset = _regOffset[_curChannel]; - if (channel.tempoReset) - { + if (channel.tempoReset) { channel.tempo = _tempo; } uint8 backup = channel.position; channel.position += channel.tempo; - if (channel.position < backup) - { - if (--channel.duration) - { + if (channel.position < backup) { + if (--channel.duration) { if (channel.duration == channel.spacing2) - noteOff (channel); + noteOff(channel); if (channel.duration == channel.spacing1 && _curChannel != 9) - noteOff (channel); - } - else - { + noteOff(channel); + } else { // An opcode is not allowed to modify its own // data pointer except through the 'dataptr' // parameter. To enforce that, we have to work @@ -875,36 +765,25 @@ AdlibDriver::executePrograms () // wrong music would play when getting the // quill in Kyra 1. uint8 *dataptr = channel.dataptr; - while (dataptr) - { + while (dataptr) { uint8 opcode = *dataptr++; uint8 param = *dataptr++; - if (opcode & 0x80) - { + if (opcode & 0x80) { opcode &= 0x7F; if (opcode >= _parserOpcodeTableSize) opcode = _parserOpcodeTableSize - 1; - debugC (9, kDebugLevelSound, - "Calling opcode '%s' (%d) (channel: %d)", - _parserOpcodeTable[opcode].name, opcode, _curChannel); - result = - (this->*(_parserOpcodeTable[opcode].function)) (dataptr, - channel, param); + debugC(9, kDebugLevelSound, "Calling opcode '%s' (%d) (channel: %d)", _parserOpcodeTable[opcode].name, opcode, _curChannel); + result = (this->*(_parserOpcodeTable[opcode].function))(dataptr, channel, param); channel.dataptr = dataptr; if (result) break; - } - else - { - debugC (9, kDebugLevelSound, - "Note on opcode 0x%02X (duration: %d) (channel: %d)", - opcode, param, _curChannel); - setupNote (opcode, channel); - noteOn (channel); - setupDuration (param, channel); - if (param) - { + } else { + debugC(9, kDebugLevelSound, "Note on opcode 0x%02X (duration: %d) (channel: %d)", opcode, param, _curChannel); + setupNote(opcode, channel); + noteOn(channel); + setupDuration(param, channel); + if (param) { channel.dataptr = dataptr; break; } @@ -913,63 +792,52 @@ AdlibDriver::executePrograms () } } - if (result == 1) - { + if (result == 1) { if (channel.primaryEffect) - (this->*(channel.primaryEffect)) (channel); + (this->*(channel.primaryEffect))(channel); if (channel.secondaryEffect) - (this->*(channel.secondaryEffect)) (channel); + (this->*(channel.secondaryEffect))(channel); } } } // -void -AdlibDriver::resetAdlibState () -{ - debugC (9, kDebugLevelSound, "resetAdlibState()"); +void AdlibDriver::resetAdlibState() { + debugC(9, kDebugLevelSound, "resetAdlibState()"); _rnd = 0x1234; // Authorize the control of the waveforms - writeOPL (0x01, 0x20); + writeOPL(0x01, 0x20); // Select FM music mode - writeOPL (0x08, 0x00); + writeOPL(0x08, 0x00); // I would guess the main purpose of this is to turn off the rhythm, // thus allowing us to use 9 melodic voices instead of 6. - writeOPL (0xBD, 0x00); + writeOPL(0xBD, 0x00); int loop = 10; - while (loop--) - { - if (loop != 9) - { + while (loop--) { + if (loop != 9) { // Silence the channel - writeOPL (0x40 + _regOffset[loop], 0x3F); - writeOPL (0x43 + _regOffset[loop], 0x3F); + writeOPL(0x40 + _regOffset[loop], 0x3F); + writeOPL(0x43 + _regOffset[loop], 0x3F); } - initChannel (_channels[loop]); + initChannel(_channels[loop]); } } // Old calling style: output0x388(0xABCD) // New calling style: writeOPL(0xAB, 0xCD) -void -AdlibDriver::writeOPL (byte reg, byte val) -{ - opl->write (reg, val); +void AdlibDriver::writeOPL(byte reg, byte val) { + opl->write(reg, val); } -void -AdlibDriver::initChannel (Channel & channel) -{ - debugC (9, kDebugLevelSound, "initChannel(%lu)", - (long) (&channel - _channels)); - memset (&channel.dataptr, 0, - sizeof (Channel) - ((char *) &channel.dataptr - (char *) &channel)); +void AdlibDriver::initChannel(Channel &channel) { + debugC(9, kDebugLevelSound, "initChannel(%lu)", (long)(&channel - _channels)); + memset(&channel.dataptr, 0, sizeof(Channel) - ((char*)&channel.dataptr - (char*)&channel)); channel.tempo = 0xFF; channel.priority = 0; @@ -979,10 +847,8 @@ AdlibDriver::initChannel (Channel & channel) channel.spacing1 = 1; } -void -AdlibDriver::noteOff (Channel & channel) -{ - debugC (9, kDebugLevelSound, "noteOff(%lu)", (long) (&channel - _channels)); +void AdlibDriver::noteOff(Channel &channel) { + debugC(9, kDebugLevelSound, "noteOff(%lu)", (long)(&channel - _channels)); // The control channel has no corresponding Adlib channel @@ -998,13 +864,11 @@ AdlibDriver::noteOff (Channel & channel) channel.regBx &= 0xDF; // Octave / F-Number / Key-On - writeOPL (0xB0 + _curChannel, channel.regBx); + writeOPL(0xB0 + _curChannel, channel.regBx); } -void -AdlibDriver::unkOutput2 (uint8 chan) -{ - debugC (9, kDebugLevelSound, "unkOutput2(%d)", chan); +void AdlibDriver::unkOutput2(uint8 chan) { + debugC(9, kDebugLevelSound, "unkOutput2(%d)", chan); // The control channel has no corresponding Adlib channel @@ -1022,13 +886,13 @@ AdlibDriver::unkOutput2 (uint8 chan) // The channel is cleared: First the attack/delay rate, then the // sustain level/release rate, and finally the note is turned off. - writeOPL (0x60 + offset, 0xFF); - writeOPL (0x63 + offset, 0xFF); + writeOPL(0x60 + offset, 0xFF); + writeOPL(0x63 + offset, 0xFF); - writeOPL (0x80 + offset, 0xFF); - writeOPL (0x83 + offset, 0xFF); + writeOPL(0x80 + offset, 0xFF); + writeOPL(0x83 + offset, 0xFF); - writeOPL (0xB0 + chan, 0x00); + writeOPL(0xB0 + chan, 0x00); // ...and then the note is turned on again, with whatever value is // still lurking in the A0 + chan register, but everything else - @@ -1047,16 +911,14 @@ AdlibDriver::unkOutput2 (uint8 chan) // http://www.advsys.net/ken - and as part of AdPlug) also seems to be // immune, but is apparently not as feature complete as MAME's. - writeOPL (0xB0 + chan, 0x20); + writeOPL(0xB0 + chan, 0x20); } // I believe this is a random number generator. It actually does seem to // generate an even distribution of almost all numbers from 0 through 65535, // though in my tests some numbers were never generated. -uint16 -AdlibDriver::getRandomNr () -{ +uint16 AdlibDriver::getRandomNr() { _rnd += 0x9248; uint16 lowBits = _rnd & 7; _rnd >>= 3; @@ -1064,19 +926,13 @@ AdlibDriver::getRandomNr () return _rnd; } -void -AdlibDriver::setupDuration (uint8 duration, Channel & channel) -{ - debugC (9, kDebugLevelSound, "setupDuration(%d, %lu)", duration, - (long) (&channel - _channels)); - if (channel.durationRandomness) - { - channel.duration = - duration + (getRandomNr () & channel.durationRandomness); +void AdlibDriver::setupDuration(uint8 duration, Channel &channel) { + debugC(9, kDebugLevelSound, "setupDuration(%d, %lu)", duration, (long)(&channel - _channels)); + if (channel.durationRandomness) { + channel.duration = duration + (getRandomNr() & channel.durationRandomness); return; } - if (channel.fractionalSpacing) - { + if (channel.fractionalSpacing) { channel.spacing2 = (duration >> 3) * channel.fractionalSpacing; } channel.duration = duration; @@ -1085,11 +941,8 @@ AdlibDriver::setupDuration (uint8 duration, Channel & channel) // This function may or may not play the note. It's usually followed by a call // to noteOn(), which will always play the current note. -void -AdlibDriver::setupNote (uint8 rawNote, Channel & channel, bool flag) -{ - debugC (9, kDebugLevelSound, "setupNote(%d, %lu)", rawNote, - (long) (&channel - _channels)); +void AdlibDriver::setupNote(uint8 rawNote, Channel &channel, bool flag) { + debugC(9, kDebugLevelSound, "setupNote(%d, %lu)", rawNote, (long)(&channel - _channels)); channel.rawNote = rawNote; @@ -1099,13 +952,10 @@ AdlibDriver::setupNote (uint8 rawNote, Channel & channel, bool flag) // There are only twelve notes. If we go outside that, we have to // adjust the note and octave. - if (note >= 12) - { + if (note >= 12) { note -= 12; octave++; - } - else if (note < 0) - { + } else if (note < 0) { note += 12; octave--; } @@ -1125,41 +975,32 @@ AdlibDriver::setupNote (uint8 rawNote, Channel & channel, bool flag) // When called from callback 41, the behaviour is slightly different: // We adjust the frequency, even when channel.unk16 is 0. - if (channel.unk16 || flag) - { + if (channel.unk16 || flag) { const uint8 *table; - if (channel.unk16 >= 0) - { + if (channel.unk16 >= 0) { table = _unkTables[(channel.rawNote & 0x0F) + 2]; freq += table[channel.unk16]; - } - else - { + } else { table = _unkTables[channel.rawNote & 0x0F]; freq -= table[-channel.unk16]; } } channel.regAx = freq & 0xFF; - channel.regBx = - (channel.regBx & 0x20) | (octave << 2) | ((freq >> 8) & 0x03); + channel.regBx = (channel.regBx & 0x20) | (octave << 2) | ((freq >> 8) & 0x03); // Keep the note on or off - writeOPL (0xA0 + _curChannel, channel.regAx); - writeOPL (0xB0 + _curChannel, channel.regBx); + writeOPL(0xA0 + _curChannel, channel.regAx); + writeOPL(0xB0 + _curChannel, channel.regBx); } -void -AdlibDriver::setupInstrument (uint8 regOffset, uint8 * dataptr, - Channel & channel) -{ - debugC (9, kDebugLevelSound, "setupInstrument(%d, %p, %lu)", regOffset, - (const void *) dataptr, (long) (&channel - _channels)); +void AdlibDriver::setupInstrument(uint8 regOffset, uint8 *dataptr, Channel &channel) { + debugC(9, kDebugLevelSound, "setupInstrument(%d, %p, %lu)", regOffset, (const void *)dataptr, (long)(&channel - _channels)); // Amplitude Modulation / Vibrato / Envelope Generator Type / // Keyboard Scaling Rate / Modulator Frequency Multiple - writeOPL (0x20 + regOffset, *dataptr++); - writeOPL (0x23 + regOffset, *dataptr++); + writeOPL(0x20 + regOffset, *dataptr++); + writeOPL(0x23 + regOffset, *dataptr++); uint8 temp = *dataptr++; @@ -1168,7 +1009,7 @@ AdlibDriver::setupInstrument (uint8 regOffset, uint8 * dataptr, // It is very likely that _curChannel really does refer to the same // channel as regOffset, but there's only one Cx register per channel. - writeOPL (0xC0 + _curChannel, temp); + writeOPL(0xC0 + _curChannel, temp); // The algorithm bit. I don't pretend to understand this fully, but // "If set to 0, operator 1 modulates operator 2. In this case, @@ -1179,37 +1020,35 @@ AdlibDriver::setupInstrument (uint8 regOffset, uint8 * dataptr, channel.twoChan = temp & 1; // Waveform Select - writeOPL (0xE0 + regOffset, *dataptr++); - writeOPL (0xE3 + regOffset, *dataptr++); + writeOPL(0xE0 + regOffset, *dataptr++); + writeOPL(0xE3 + regOffset, *dataptr++); channel.opLevel1 = *dataptr++; channel.opLevel2 = *dataptr++; // Level Key Scaling / Total Level - writeOPL (0x40 + regOffset, calculateOpLevel1 (channel)); - writeOPL (0x43 + regOffset, calculateOpLevel2 (channel)); + writeOPL(0x40 + regOffset, calculateOpLevel1(channel)); + writeOPL(0x43 + regOffset, calculateOpLevel2(channel)); // Attack Rate / Decay Rate - writeOPL (0x60 + regOffset, *dataptr++); - writeOPL (0x63 + regOffset, *dataptr++); + writeOPL(0x60 + regOffset, *dataptr++); + writeOPL(0x63 + regOffset, *dataptr++); // Sustain Level / Release Rate - writeOPL (0x80 + regOffset, *dataptr++); - writeOPL (0x83 + regOffset, *dataptr++); + writeOPL(0x80 + regOffset, *dataptr++); + writeOPL(0x83 + regOffset, *dataptr++); } // Apart from playing the note, this function also updates the variables for // primary effect 2. -void -AdlibDriver::noteOn (Channel & channel) -{ - debugC (9, kDebugLevelSound, "noteOn(%lu)", (long) (&channel - _channels)); +void AdlibDriver::noteOn(Channel &channel) { + debugC(9, kDebugLevelSound, "noteOn(%lu)", (long)(&channel - _channels)); // The "note on" bit is set, and the current note is played. channel.regBx |= 0x20; - writeOPL (0xB0 + _curChannel, channel.regBx); + writeOPL(0xB0 + _curChannel, channel.regBx); int8 shift = 9 - channel.unk33; uint16 temp = channel.regAx | (channel.regBx << 8); @@ -1217,16 +1056,13 @@ AdlibDriver::noteOn (Channel & channel) channel.unk38 = channel.unk36; } -void -AdlibDriver::adjustVolume (Channel & channel) -{ - debugC (9, kDebugLevelSound, "adjustVolume(%lu)", - (long) (&channel - _channels)); +void AdlibDriver::adjustVolume(Channel &channel) { + debugC(9, kDebugLevelSound, "adjustVolume(%lu)", (long)(&channel - _channels)); // Level Key Scaling / Total Level - writeOPL (0x43 + _regOffset[_curChannel], calculateOpLevel2 (channel)); + writeOPL(0x43 + _regOffset[_curChannel], calculateOpLevel2(channel)); if (channel.twoChan) - writeOPL (0x40 + _regOffset[_curChannel], calculateOpLevel1 (channel)); + writeOPL(0x40 + _regOffset[_curChannel], calculateOpLevel1(channel)); } // This is presumably only used for some sound effects, e.g. Malcolm blowing up @@ -1245,11 +1081,8 @@ AdlibDriver::adjustVolume (Channel & channel) // unk30 - modifies the frequency // unk31 - determines how often the notes are played -void -AdlibDriver::primaryEffect1 (Channel & channel) -{ - debugC (9, kDebugLevelSound, "Calling primaryEffect1 (channel: %d)", - _curChannel); +void AdlibDriver::primaryEffect1(Channel &channel) { + debugC(9, kDebugLevelSound, "Calling primaryEffect1 (channel: %d)", _curChannel); uint8 temp = channel.unk31; channel.unk31 += channel.unk29; if (channel.unk31 >= temp) @@ -1262,13 +1095,11 @@ AdlibDriver::primaryEffect1 (Channel & channel) // that it won't be affected by any of the calculations below. uint16 unk2 = ((channel.regBx & 0x20) << 8) | (channel.regBx & 0x1C); - int16 unk3 = (int16) channel.unk30; + int16 unk3 = (int16)channel.unk30; - if (unk3 >= 0) - { + if (unk3 >= 0) { unk1 += unk3; - if (unk1 >= 734) - { + if (unk1 >= 734) { // The new frequency is too high. Shift it down and go // up one octave. unk1 >>= 1; @@ -1277,12 +1108,9 @@ AdlibDriver::primaryEffect1 (Channel & channel) unk2 = (unk2 & 0xFF00) | ((unk2 + 4) & 0xFF); unk2 &= 0xFF1C; } - } - else - { + } else { unk1 += unk3; - if (unk1 < 388) - { + if (unk1 < 388) { // The new frequency is too low. Shift it up and go // down one octave. unk1 <<= 1; @@ -1296,7 +1124,7 @@ AdlibDriver::primaryEffect1 (Channel & channel) // Make sure that the new frequency is still a 10-bit value. unk1 &= 0x3FF; - writeOPL (0xA0 + _curChannel, unk1 & 0xFF); + writeOPL(0xA0 + _curChannel, unk1 & 0xFF); channel.regAx = unk1 & 0xFF; // Shift down the "note on" bit again. @@ -1304,7 +1132,7 @@ AdlibDriver::primaryEffect1 (Channel & channel) value |= (unk2 >> 8) & 0xFF; value |= unk2 & 0xFF; - writeOPL (0xB0 + _curChannel, value); + writeOPL(0xB0 + _curChannel, value); channel.regBx = value; } @@ -1336,24 +1164,18 @@ AdlibDriver::primaryEffect1 (Channel & channel) // Note that unk41 is never initialised. Not that it should matter much, but it // is a bit sloppy. -void -AdlibDriver::primaryEffect2 (Channel & channel) -{ - debugC (9, kDebugLevelSound, "Calling primaryEffect2 (channel: %d)", - _curChannel); - if (channel.unk38) - { +void AdlibDriver::primaryEffect2(Channel &channel) { + debugC(9, kDebugLevelSound, "Calling primaryEffect2 (channel: %d)", _curChannel); + if (channel.unk38) { --channel.unk38; return; } uint8 temp = channel.unk41; channel.unk41 += channel.unk32; - if (channel.unk41 < temp) - { + if (channel.unk41 < temp) { uint16 unk1 = channel.unk37; - if (!(--channel.unk34)) - { + if (!(--channel.unk34)) { unk1 ^= 0xFFFF; ++unk1; channel.unk37 = unk1; @@ -1367,8 +1189,8 @@ AdlibDriver::primaryEffect2 (Channel & channel) channel.regBx = (channel.regBx & 0xFC) | (unk2 >> 8); // Octave / F-Number / Key-On - writeOPL (0xA0 + _curChannel, channel.regAx); - writeOPL (0xB0 + _curChannel, channel.regBx); + writeOPL(0xA0 + _curChannel, channel.regAx); + writeOPL(0xB0 + _curChannel, channel.regBx); } } @@ -1397,31 +1219,22 @@ AdlibDriver::primaryEffect2 (Channel & channel) // unk22 - the operation to perform // offset - the offset to the data chunk -void -AdlibDriver::secondaryEffect1 (Channel & channel) -{ - debugC (9, kDebugLevelSound, "Calling secondaryEffect1 (channel: %d)", - _curChannel); +void AdlibDriver::secondaryEffect1(Channel &channel) { + debugC(9, kDebugLevelSound, "Calling secondaryEffect1 (channel: %d)", _curChannel); uint8 temp = channel.unk18; channel.unk18 += channel.unk19; - if (channel.unk18 < temp) - { - if (--channel.unk21 < 0) - { + if (channel.unk18 < temp) { + if (--channel.unk21 < 0) { channel.unk21 = channel.unk20; } - writeOPL (channel.unk22 + _curRegOffset, - _soundData[channel.offset + channel.unk21]); + writeOPL(channel.unk22 + _curRegOffset, _soundData[channel.offset + channel.unk21]); } } -uint8 -AdlibDriver::calculateOpLevel1 (Channel & channel) -{ +uint8 AdlibDriver::calculateOpLevel1(Channel &channel) { int8 value = channel.opLevel1 & 0x3F; - if (channel.twoChan) - { + if (channel.twoChan) { value += channel.opExtraLevel1; value += channel.opExtraLevel2; value += channel.opExtraLevel3; @@ -1429,12 +1242,10 @@ AdlibDriver::calculateOpLevel1 (Channel & channel) // Preserve the scaling level bits from opLevel1 - return checkValue (value) | (channel.opLevel1 & 0xC0); + return checkValue(value) | (channel.opLevel1 & 0xC0); } -uint8 -AdlibDriver::calculateOpLevel2 (Channel & channel) -{ +uint8 AdlibDriver::calculateOpLevel2(Channel &channel) { int8 value = channel.opLevel2 & 0x3F; value += channel.opExtraLevel1; @@ -1443,189 +1254,135 @@ AdlibDriver::calculateOpLevel2 (Channel & channel) // Preserve the scaling level bits from opLevel2 - return checkValue (value) | (channel.opLevel2 & 0xC0); + return checkValue(value) | (channel.opLevel2 & 0xC0); } // parser opcodes -int -AdlibDriver::update_setRepeat (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::update_setRepeat(uint8 *&dataptr, Channel &channel, uint8 value) { channel.repeatCounter = value; return 0; } -int -AdlibDriver::update_checkRepeat (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::update_checkRepeat(uint8 *&dataptr, Channel &channel, uint8 value) { ++dataptr; - if (--channel.repeatCounter) - { - int16 add = READ_LE_UINT16 (dataptr - 2); + if (--channel.repeatCounter) { + int16 add = READ_LE_UINT16(dataptr - 2); dataptr += add; } return 0; } -int -AdlibDriver::update_setupProgram (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::update_setupProgram(uint8 *&dataptr, Channel &channel, uint8 value) { if (value == 0xFF) return 0; - uint8 *ptr = getProgram (value); + uint8 *ptr = getProgram(value); uint8 chan = *ptr++; uint8 priority = *ptr++; - Channel & channel2 = _channels[chan]; + Channel &channel2 = _channels[chan]; - if (priority >= channel2.priority) - { + if (priority >= channel2.priority) { _flagTrigger = 1; _flags |= 8; - initChannel (channel2); + initChannel(channel2); channel2.priority = priority; channel2.dataptr = ptr; channel2.tempo = 0xFF; channel2.position = 0xFF; channel2.duration = 1; - unkOutput2 (chan); + unkOutput2(chan); } return 0; } -int -AdlibDriver::update_setNoteSpacing (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::update_setNoteSpacing(uint8 *&dataptr, Channel &channel, uint8 value) { channel.spacing1 = value; return 0; } -int -AdlibDriver::update_jump (uint8 * &dataptr, Channel & channel, uint8 value) -{ +int AdlibDriver::update_jump(uint8 *&dataptr, Channel &channel, uint8 value) { --dataptr; - int16 add = READ_LE_UINT16 (dataptr); - dataptr += 2; + int16 add = READ_LE_UINT16(dataptr); dataptr += 2; dataptr += add; return 0; } -int -AdlibDriver::update_jumpToSubroutine (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::update_jumpToSubroutine(uint8 *&dataptr, Channel &channel, uint8 value) { --dataptr; - int16 add = READ_LE_UINT16 (dataptr); - dataptr += 2; + int16 add = READ_LE_UINT16(dataptr); dataptr += 2; channel.dataptrStack[channel.dataptrStackPos++] = dataptr; dataptr += add; return 0; } -int -AdlibDriver::update_returnFromSubroutine (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::update_returnFromSubroutine(uint8 *&dataptr, Channel &channel, uint8 value) { dataptr = channel.dataptrStack[--channel.dataptrStackPos]; return 0; } -int -AdlibDriver::update_setBaseOctave (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::update_setBaseOctave(uint8 *&dataptr, Channel &channel, uint8 value) { channel.baseOctave = value; return 0; } -int -AdlibDriver::update_stopChannel (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::update_stopChannel(uint8 *&dataptr, Channel &channel, uint8 value) { channel.priority = 0; - if (_curChannel != 9) - { - noteOff (channel); + if (_curChannel != 9) { + noteOff(channel); } dataptr = 0; return 2; } -int -AdlibDriver::update_playRest (uint8 * &dataptr, Channel & channel, - uint8 value) -{ - setupDuration (value, channel); - noteOff (channel); +int AdlibDriver::update_playRest(uint8 *&dataptr, Channel &channel, uint8 value) { + setupDuration(value, channel); + noteOff(channel); return (value != 0); } -int -AdlibDriver::update_writeAdlib (uint8 * &dataptr, Channel & channel, - uint8 value) -{ - writeOPL (value, *dataptr++); +int AdlibDriver::update_writeAdlib(uint8 *&dataptr, Channel &channel, uint8 value) { + writeOPL(value, *dataptr++); return 0; } -int -AdlibDriver::update_setupNoteAndDuration (uint8 * &dataptr, Channel & channel, - uint8 value) -{ - setupNote (value, channel); +int AdlibDriver::update_setupNoteAndDuration(uint8 *&dataptr, Channel &channel, uint8 value) { + setupNote(value, channel); value = *dataptr++; - setupDuration (value, channel); + setupDuration(value, channel); return (value != 0); } -int -AdlibDriver::update_setBaseNote (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::update_setBaseNote(uint8 *&dataptr, Channel &channel, uint8 value) { channel.baseNote = value; return 0; } -int -AdlibDriver::update_setupSecondaryEffect1 (uint8 * &dataptr, - Channel & channel, uint8 value) -{ +int AdlibDriver::update_setupSecondaryEffect1(uint8 *&dataptr, Channel &channel, uint8 value) { channel.unk18 = value; channel.unk19 = value; channel.unk20 = channel.unk21 = *dataptr++; channel.unk22 = *dataptr++; - channel.offset = READ_LE_UINT16 (dataptr); - dataptr += 2; + channel.offset = READ_LE_UINT16(dataptr); dataptr += 2; channel.secondaryEffect = &AdlibDriver::secondaryEffect1; return 0; } -int -AdlibDriver::update_stopOtherChannel (uint8 * &dataptr, Channel & channel, - uint8 value) -{ - Channel & channel2 = _channels[value]; +int AdlibDriver::update_stopOtherChannel(uint8 *&dataptr, Channel &channel, uint8 value) { + Channel &channel2 = _channels[value]; channel2.duration = 0; channel2.priority = 0; channel2.dataptr = 0; return 0; } -int -AdlibDriver::update_waitForEndOfProgram (uint8 * &dataptr, Channel & channel, - uint8 value) -{ - uint8 *ptr = getProgram (value); +int AdlibDriver::update_waitForEndOfProgram(uint8 *&dataptr, Channel &channel, uint8 value) { + uint8 *ptr = getProgram(value); uint8 chan = *ptr; - if (!_channels[chan].dataptr) - { + if (!_channels[chan].dataptr) { return 0; } @@ -1633,48 +1390,33 @@ AdlibDriver::update_waitForEndOfProgram (uint8 * &dataptr, Channel & channel, return 2; } -int -AdlibDriver::update_setupInstrument (uint8 * &dataptr, Channel & channel, - uint8 value) -{ - setupInstrument (_curRegOffset, getInstrument (value), channel); +int AdlibDriver::update_setupInstrument(uint8 *&dataptr, Channel &channel, uint8 value) { + setupInstrument(_curRegOffset, getInstrument(value), channel); return 0; } -int -AdlibDriver::update_setupPrimaryEffect1 (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::update_setupPrimaryEffect1(uint8 *&dataptr, Channel &channel, uint8 value) { channel.unk29 = value; - channel.unk30 = READ_BE_UINT16 (dataptr); + channel.unk30 = READ_BE_UINT16(dataptr); dataptr += 2; channel.primaryEffect = &AdlibDriver::primaryEffect1; channel.unk31 = 0xFF; return 0; } -int -AdlibDriver::update_removePrimaryEffect1 (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::update_removePrimaryEffect1(uint8 *&dataptr, Channel &channel, uint8 value) { --dataptr; channel.primaryEffect = 0; channel.unk30 = 0; return 0; } -int -AdlibDriver::update_setBaseFreq (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::update_setBaseFreq(uint8 *&dataptr, Channel &channel, uint8 value) { channel.baseFreq = value; return 0; } -int -AdlibDriver::update_setupPrimaryEffect2 (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::update_setupPrimaryEffect2(uint8 *&dataptr, Channel &channel, uint8 value) { channel.unk32 = value; channel.unk33 = *dataptr++; uint8 temp = *dataptr++; @@ -1685,18 +1427,12 @@ AdlibDriver::update_setupPrimaryEffect2 (uint8 * &dataptr, Channel & channel, return 0; } -int -AdlibDriver::update_setPriority (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::update_setPriority(uint8 *&dataptr, Channel &channel, uint8 value) { channel.priority = value; return 0; } -int -AdlibDriver::updateCallback23 (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::updateCallback23(uint8 *&dataptr, Channel &channel, uint8 value) { value >>= 1; _unkValue1 = _unkValue2 = value; _unkValue3 = 0xFF; @@ -1704,21 +1440,15 @@ AdlibDriver::updateCallback23 (uint8 * &dataptr, Channel & channel, return 0; } -int -AdlibDriver::updateCallback24 (uint8 * &dataptr, Channel & channel, - uint8 value) -{ - if (_unkValue5) - { - if (_unkValue4 & value) - { +int AdlibDriver::updateCallback24(uint8 *&dataptr, Channel &channel, uint8 value) { + if (_unkValue5) { + if (_unkValue4 & value) { _unkValue5 = 0; return 0; } } - if (!(value & _unkValue4)) - { + if (!(value & _unkValue4)) { ++_unkValue5; } @@ -1727,98 +1457,68 @@ AdlibDriver::updateCallback24 (uint8 * &dataptr, Channel & channel, return 2; } -int -AdlibDriver::update_setExtraLevel1 (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::update_setExtraLevel1(uint8 *&dataptr, Channel &channel, uint8 value) { channel.opExtraLevel1 = value; - adjustVolume (channel); + adjustVolume(channel); return 0; } -int -AdlibDriver::update_setupDuration (uint8 * &dataptr, Channel & channel, - uint8 value) -{ - setupDuration (value, channel); +int AdlibDriver::update_setupDuration(uint8 *&dataptr, Channel &channel, uint8 value) { + setupDuration(value, channel); return (value != 0); } -int -AdlibDriver::update_playNote (uint8 * &dataptr, Channel & channel, - uint8 value) -{ - setupDuration (value, channel); - noteOn (channel); +int AdlibDriver::update_playNote(uint8 *&dataptr, Channel &channel, uint8 value) { + setupDuration(value, channel); + noteOn(channel); return (value != 0); } -int -AdlibDriver::update_setFractionalNoteSpacing (uint8 * &dataptr, - Channel & channel, uint8 value) -{ +int AdlibDriver::update_setFractionalNoteSpacing(uint8 *&dataptr, Channel &channel, uint8 value) { channel.fractionalSpacing = value & 7; return 0; } -int -AdlibDriver::update_setTempo (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::update_setTempo(uint8 *&dataptr, Channel &channel, uint8 value) { _tempo = value; return 0; } -int -AdlibDriver::update_removeSecondaryEffect1 (uint8 * &dataptr, - Channel & channel, uint8 value) -{ +int AdlibDriver::update_removeSecondaryEffect1(uint8 *&dataptr, Channel &channel, uint8 value) { --dataptr; channel.secondaryEffect = 0; return 0; } -int -AdlibDriver::update_setChannelTempo (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::update_setChannelTempo(uint8 *&dataptr, Channel &channel, uint8 value) { channel.tempo = value; return 0; } -int -AdlibDriver::update_setExtraLevel3 (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::update_setExtraLevel3(uint8 *&dataptr, Channel &channel, uint8 value) { channel.opExtraLevel3 = value; return 0; } -int -AdlibDriver::update_setExtraLevel2 (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::update_setExtraLevel2(uint8 *&dataptr, Channel &channel, uint8 value) { int channelBackUp = _curChannel; _curChannel = value; - Channel & channel2 = _channels[value]; + Channel &channel2 = _channels[value]; channel2.opExtraLevel2 = *dataptr++; - adjustVolume (channel2); + adjustVolume(channel2); _curChannel = channelBackUp; return 0; } -int -AdlibDriver::update_changeExtraLevel2 (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::update_changeExtraLevel2(uint8 *&dataptr, Channel &channel, uint8 value) { int channelBackUp = _curChannel; _curChannel = value; - Channel & channel2 = _channels[value]; + Channel &channel2 = _channels[value]; channel2.opExtraLevel2 += *dataptr++; - adjustVolume (channel2); + adjustVolume(channel2); _curChannel = channelBackUp; return 0; @@ -1827,142 +1527,109 @@ AdlibDriver::update_changeExtraLevel2 (uint8 * &dataptr, Channel & channel, // Apart from initialising to zero, these two functions are the only ones that // modify _vibratoAndAMDepthBits. -int -AdlibDriver::update_setAMDepth (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::update_setAMDepth(uint8 *&dataptr, Channel &channel, uint8 value) { if (value & 1) _vibratoAndAMDepthBits |= 0x80; else _vibratoAndAMDepthBits &= 0x7F; - writeOPL (0xBD, _vibratoAndAMDepthBits); + writeOPL(0xBD, _vibratoAndAMDepthBits); return 0; } -int -AdlibDriver::update_setVibratoDepth (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::update_setVibratoDepth(uint8 *&dataptr, Channel &channel, uint8 value) { if (value & 1) _vibratoAndAMDepthBits |= 0x40; else _vibratoAndAMDepthBits &= 0xBF; - writeOPL (0xBD, _vibratoAndAMDepthBits); + writeOPL(0xBD, _vibratoAndAMDepthBits); return 0; } -int -AdlibDriver::update_changeExtraLevel1 (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::update_changeExtraLevel1(uint8 *&dataptr, Channel &channel, uint8 value) { channel.opExtraLevel1 += value; - adjustVolume (channel); + adjustVolume(channel); return 0; } -int -AdlibDriver::updateCallback38 (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::updateCallback38(uint8 *&dataptr, Channel &channel, uint8 value) { int channelBackUp = _curChannel; _curChannel = value; - Channel & channel2 = _channels[value]; + Channel &channel2 = _channels[value]; channel2.duration = channel2.priority = 0; channel2.dataptr = 0; channel2.opExtraLevel2 = 0; - if (value != 9) - { + if (value != 9) { uint8 outValue = _regOffset[value]; // Feedback strength / Connection type - writeOPL (0xC0 + _curChannel, 0x00); + writeOPL(0xC0 + _curChannel, 0x00); // Key scaling level / Operator output level - writeOPL (0x43 + outValue, 0x3F); + writeOPL(0x43 + outValue, 0x3F); // Sustain Level / Release Rate - writeOPL (0x83 + outValue, 0xFF); + writeOPL(0x83 + outValue, 0xFF); // Key On / Octave / Frequency - writeOPL (0xB0 + _curChannel, 0x00); + writeOPL(0xB0 + _curChannel, 0x00); } _curChannel = channelBackUp; return 0; } -int -AdlibDriver::updateCallback39 (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::updateCallback39(uint8 *&dataptr, Channel &channel, uint8 value) { uint16 unk = *dataptr++; unk |= value << 8; - unk &= getRandomNr (); + unk &= getRandomNr(); uint16 unk2 = ((channel.regBx & 0x1F) << 8) | channel.regAx; unk2 += unk; unk2 |= ((channel.regBx & 0x20) << 8); // Frequency - writeOPL (0xA0 + _curChannel, unk2 & 0xFF); + writeOPL(0xA0 + _curChannel, unk2 & 0xFF); // Key On / Octave / Frequency - writeOPL (0xB0 + _curChannel, (unk2 & 0xFF00) >> 8); + writeOPL(0xB0 + _curChannel, (unk2 & 0xFF00) >> 8); return 0; } -int -AdlibDriver::update_removePrimaryEffect2 (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::update_removePrimaryEffect2(uint8 *&dataptr, Channel &channel, uint8 value) { --dataptr; channel.primaryEffect = 0; return 0; } -int -AdlibDriver::updateCallback41 (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::updateCallback41(uint8 *&dataptr, Channel &channel, uint8 value) { channel.unk16 = value; - setupNote (channel.rawNote, channel, true); + setupNote(channel.rawNote, channel, true); return 0; } -int -AdlibDriver::update_resetToGlobalTempo (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::update_resetToGlobalTempo(uint8 *&dataptr, Channel &channel, uint8 value) { --dataptr; channel.tempo = _tempo; return 0; } -int -AdlibDriver::update_nop1 (uint8 * &dataptr, Channel & channel, uint8 value) -{ +int AdlibDriver::update_nop1(uint8 *&dataptr, Channel &channel, uint8 value) { --dataptr; return 0; } -int -AdlibDriver::update_setDurationRandomness (uint8 * &dataptr, - Channel & channel, uint8 value) -{ +int AdlibDriver::update_setDurationRandomness(uint8 *&dataptr, Channel &channel, uint8 value) { channel.durationRandomness = value; return 0; } -int -AdlibDriver::update_changeChannelTempo (uint8 * &dataptr, Channel & channel, - uint8 value) -{ - int tempo = channel.tempo + (int8) value; +int AdlibDriver::update_changeChannelTempo(uint8 *&dataptr, Channel &channel, uint8 value) { + int tempo = channel.tempo + (int8)value; if (tempo <= 0) tempo = 1; @@ -1973,17 +1640,13 @@ AdlibDriver::update_changeChannelTempo (uint8 * &dataptr, Channel & channel, return 0; } -int -AdlibDriver::updateCallback46 (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::updateCallback46(uint8 *&dataptr, Channel &channel, uint8 value) { uint8 entry = *dataptr++; _tablePtr1 = _unkTable2[entry++]; _tablePtr2 = _unkTable2[entry]; - if (value == 2) - { + if (value == 2) { // Frequency - writeOPL (0xA0, _tablePtr2[0]); + writeOPL(0xA0, _tablePtr2[0]); } return 0; } @@ -1991,53 +1654,48 @@ AdlibDriver::updateCallback46 (uint8 * &dataptr, Channel & channel, // TODO: This is really the same as update_nop1(), so they should be combined // into one single update_nop(). -int -AdlibDriver::update_nop2 (uint8 * &dataptr, Channel & channel, uint8 value) -{ +int AdlibDriver::update_nop2(uint8 *&dataptr, Channel &channel, uint8 value) { --dataptr; return 0; } -int -AdlibDriver::update_setupRhythmSection (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::update_setupRhythmSection(uint8 *&dataptr, Channel &channel, uint8 value) { int channelBackUp = _curChannel; int regOffsetBackUp = _curRegOffset; _curChannel = 6; _curRegOffset = _regOffset[6]; - setupInstrument (_curRegOffset, getInstrument (value), channel); + setupInstrument(_curRegOffset, getInstrument(value), channel); _unkValue6 = channel.opLevel2; _curChannel = 7; _curRegOffset = _regOffset[7]; - setupInstrument (_curRegOffset, getInstrument (*dataptr++), channel); + setupInstrument(_curRegOffset, getInstrument(*dataptr++), channel); _unkValue7 = channel.opLevel1; _unkValue8 = channel.opLevel2; _curChannel = 8; _curRegOffset = _regOffset[8]; - setupInstrument (_curRegOffset, getInstrument (*dataptr++), channel); + setupInstrument(_curRegOffset, getInstrument(*dataptr++), channel); _unkValue9 = channel.opLevel1; _unkValue10 = channel.opLevel2; // Octave / F-Number / Key-On for channels 6, 7 and 8 _channels[6].regBx = *dataptr++ & 0x2F; - writeOPL (0xB6, _channels[6].regBx); - writeOPL (0xA6, *dataptr++); + writeOPL(0xB6, _channels[6].regBx); + writeOPL(0xA6, *dataptr++); _channels[7].regBx = *dataptr++ & 0x2F; - writeOPL (0xB7, _channels[7].regBx); - writeOPL (0xA7, *dataptr++); + writeOPL(0xB7, _channels[7].regBx); + writeOPL(0xA7, *dataptr++); _channels[8].regBx = *dataptr++ & 0x2F; - writeOPL (0xB8, _channels[8].regBx); - writeOPL (0xA8, *dataptr++); + writeOPL(0xB8, _channels[8].regBx); + writeOPL(0xA8, *dataptr++); _rhythmSectionBits = 0x20; @@ -2046,17 +1704,14 @@ AdlibDriver::update_setupRhythmSection (uint8 * &dataptr, Channel & channel, return 0; } -int -AdlibDriver::update_playRhythmSection (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::update_playRhythmSection(uint8 *&dataptr, Channel &channel, uint8 value) { // Any instrument that we want to play, and which was already playing, // is temporarily keyed off. Instruments that were off already, or // which we don't want to play, retain their old on/off status. This is // probably so that the instrument's envelope is played from its // beginning again... - writeOPL (0xBD, (_rhythmSectionBits & ~(value & 0x1F)) | 0x20); + writeOPL(0xBD, (_rhythmSectionBits & ~(value & 0x1F)) | 0x20); // ...but since we only set the rhythm instrument bits, and never clear // them (until the entire rhythm section is disabled), I'm not sure how @@ -2065,201 +1720,155 @@ AdlibDriver::update_playRhythmSection (uint8 * &dataptr, Channel & channel, _rhythmSectionBits |= value; - writeOPL (0xBD, _vibratoAndAMDepthBits | 0x20 | _rhythmSectionBits); + writeOPL(0xBD, _vibratoAndAMDepthBits | 0x20 | _rhythmSectionBits); return 0; } -int -AdlibDriver::update_removeRhythmSection (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::update_removeRhythmSection(uint8 *&dataptr, Channel &channel, uint8 value) { --dataptr; _rhythmSectionBits = 0; // All the rhythm bits are cleared. The AM and Vibrato depth bits // remain unchanged. - writeOPL (0xBD, _vibratoAndAMDepthBits); + writeOPL(0xBD, _vibratoAndAMDepthBits); return 0; } -int -AdlibDriver::updateCallback51 (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::updateCallback51(uint8 *&dataptr, Channel &channel, uint8 value) { uint8 value2 = *dataptr++; - if (value & 1) - { + if (value & 1) { _unkValue12 = value2; // Channel 7, op1: Level Key Scaling / Total Level - writeOPL (0x51, - checkValue (value2 + _unkValue7 + _unkValue11 + _unkValue12)); + writeOPL(0x51, checkValue(value2 + _unkValue7 + _unkValue11 + _unkValue12)); } - if (value & 2) - { + if (value & 2) { _unkValue14 = value2; // Channel 8, op2: Level Key Scaling / Total Level - writeOPL (0x55, - checkValue (value2 + _unkValue10 + _unkValue13 + _unkValue14)); + writeOPL(0x55, checkValue(value2 + _unkValue10 + _unkValue13 + _unkValue14)); } - if (value & 4) - { + if (value & 4) { _unkValue15 = value2; // Channel 8, op1: Level Key Scaling / Total Level - writeOPL (0x52, - checkValue (value2 + _unkValue9 + _unkValue16 + _unkValue15)); + writeOPL(0x52, checkValue(value2 + _unkValue9 + _unkValue16 + _unkValue15)); } - if (value & 8) - { + if (value & 8) { _unkValue18 = value2; // Channel 7, op2: Level Key Scaling / Total Level - writeOPL (0x54, - checkValue (value2 + _unkValue8 + _unkValue17 + _unkValue18)); + writeOPL(0x54, checkValue(value2 + _unkValue8 + _unkValue17 + _unkValue18)); } - if (value & 16) - { + if (value & 16) { _unkValue20 = value2; // Channel 6, op2: Level Key Scaling / Total Level - writeOPL (0x53, - checkValue (value2 + _unkValue6 + _unkValue19 + _unkValue20)); + writeOPL(0x53, checkValue(value2 + _unkValue6 + _unkValue19 + _unkValue20)); } return 0; } -int -AdlibDriver::updateCallback52 (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::updateCallback52(uint8 *&dataptr, Channel &channel, uint8 value) { uint8 value2 = *dataptr++; - if (value & 1) - { - _unkValue11 = - checkValue (value2 + _unkValue7 + _unkValue11 + _unkValue12); + if (value & 1) { + _unkValue11 = checkValue(value2 + _unkValue7 + _unkValue11 + _unkValue12); // Channel 7, op1: Level Key Scaling / Total Level - writeOPL (0x51, _unkValue11); + writeOPL(0x51, _unkValue11); } - if (value & 2) - { - _unkValue13 = - checkValue (value2 + _unkValue10 + _unkValue13 + _unkValue14); + if (value & 2) { + _unkValue13 = checkValue(value2 + _unkValue10 + _unkValue13 + _unkValue14); // Channel 8, op2: Level Key Scaling / Total Level - writeOPL (0x55, _unkValue13); + writeOPL(0x55, _unkValue13); } - if (value & 4) - { - _unkValue16 = - checkValue (value2 + _unkValue9 + _unkValue16 + _unkValue15); + if (value & 4) { + _unkValue16 = checkValue(value2 + _unkValue9 + _unkValue16 + _unkValue15); // Channel 8, op1: Level Key Scaling / Total Level - writeOPL (0x52, _unkValue16); + writeOPL(0x52, _unkValue16); } - if (value & 8) - { - _unkValue17 = - checkValue (value2 + _unkValue8 + _unkValue17 + _unkValue18); + if (value & 8) { + _unkValue17 = checkValue(value2 + _unkValue8 + _unkValue17 + _unkValue18); // Channel 7, op2: Level Key Scaling / Total Level - writeOPL (0x54, _unkValue17); + writeOPL(0x54, _unkValue17); } - if (value & 16) - { - _unkValue19 = - checkValue (value2 + _unkValue6 + _unkValue19 + _unkValue20); + if (value & 16) { + _unkValue19 = checkValue(value2 + _unkValue6 + _unkValue19 + _unkValue20); // Channel 6, op2: Level Key Scaling / Total Level - writeOPL (0x53, _unkValue19); + writeOPL(0x53, _unkValue19); } return 0; } -int -AdlibDriver::updateCallback53 (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::updateCallback53(uint8 *&dataptr, Channel &channel, uint8 value) { uint8 value2 = *dataptr++; - if (value & 1) - { + if (value & 1) { _unkValue11 = value2; // Channel 7, op1: Level Key Scaling / Total Level - writeOPL (0x51, checkValue (value2 + _unkValue7 + _unkValue12)); + writeOPL(0x51, checkValue(value2 + _unkValue7 + _unkValue12)); } - if (value & 2) - { + if (value & 2) { _unkValue13 = value2; // Channel 8, op2: Level Key Scaling / Total Level - writeOPL (0x55, checkValue (value2 + _unkValue10 + _unkValue14)); + writeOPL(0x55, checkValue(value2 + _unkValue10 + _unkValue14)); } - if (value & 4) - { + if (value & 4) { _unkValue16 = value2; // Channel 8, op1: Level Key Scaling / Total Level - writeOPL (0x52, checkValue (value2 + _unkValue9 + _unkValue15)); + writeOPL(0x52, checkValue(value2 + _unkValue9 + _unkValue15)); } - if (value & 8) - { + if (value & 8) { _unkValue17 = value2; // Channel 7, op2: Level Key Scaling / Total Level - writeOPL (0x54, checkValue (value2 + _unkValue8 + _unkValue18)); + writeOPL(0x54, checkValue(value2 + _unkValue8 + _unkValue18)); } - if (value & 16) - { + if (value & 16) { _unkValue19 = value2; // Channel 6, op2: Level Key Scaling / Total Level - writeOPL (0x53, checkValue (value2 + _unkValue6 + _unkValue20)); + writeOPL(0x53, checkValue(value2 + _unkValue6 + _unkValue20)); } return 0; } -int -AdlibDriver::update_setSoundTrigger (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::update_setSoundTrigger(uint8 *&dataptr, Channel &channel, uint8 value) { _soundTrigger = value; return 0; } -int -AdlibDriver::update_setTempoReset (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::update_setTempoReset(uint8 *&dataptr, Channel &channel, uint8 value) { channel.tempoReset = value; return 0; } -int -AdlibDriver::updateCallback56 (uint8 * &dataptr, Channel & channel, - uint8 value) -{ +int AdlibDriver::updateCallback56(uint8 *&dataptr, Channel &channel, uint8 value) { channel.unk39 = value; channel.unk40 = *dataptr++; return 0; @@ -2269,163 +1878,157 @@ AdlibDriver::updateCallback56 (uint8 * &dataptr, Channel & channel, #define COMMAND(x) { &AdlibDriver::x, #x } -void -AdlibDriver::setupOpcodeList () -{ +void AdlibDriver::setupOpcodeList() { static const OpcodeEntry opcodeList[] = { - COMMAND (snd_ret0x100), - COMMAND (snd_ret0x1983), - COMMAND (snd_initDriver), - COMMAND (snd_deinitDriver), - COMMAND (snd_setSoundData), - COMMAND (snd_unkOpcode1), - COMMAND (snd_startSong), - COMMAND (snd_unkOpcode2), - COMMAND (snd_unkOpcode3), - COMMAND (snd_readByte), - COMMAND (snd_writeByte), - COMMAND (snd_getSoundTrigger), - COMMAND (snd_unkOpcode4), - COMMAND (snd_dummy), - COMMAND (snd_getNullvar4), - COMMAND (snd_setNullvar3), - COMMAND (snd_setFlag), - COMMAND (snd_clearFlag) + COMMAND(snd_ret0x100), + COMMAND(snd_ret0x1983), + COMMAND(snd_initDriver), + COMMAND(snd_deinitDriver), + COMMAND(snd_setSoundData), + COMMAND(snd_unkOpcode1), + COMMAND(snd_startSong), + COMMAND(snd_unkOpcode2), + COMMAND(snd_unkOpcode3), + COMMAND(snd_readByte), + COMMAND(snd_writeByte), + COMMAND(snd_getSoundTrigger), + COMMAND(snd_unkOpcode4), + COMMAND(snd_dummy), + COMMAND(snd_getNullvar4), + COMMAND(snd_setNullvar3), + COMMAND(snd_setFlag), + COMMAND(snd_clearFlag) }; _opcodeList = opcodeList; - _opcodesEntries = ARRAYSIZE (opcodeList); + _opcodesEntries = ARRAYSIZE(opcodeList); } -void -AdlibDriver::setupParserOpcodeTable () -{ +void AdlibDriver::setupParserOpcodeTable() { static const ParserOpcode parserOpcodeTable[] = { // 0 - COMMAND (update_setRepeat), - COMMAND (update_checkRepeat), - COMMAND (update_setupProgram), - COMMAND (update_setNoteSpacing), + COMMAND(update_setRepeat), + COMMAND(update_checkRepeat), + COMMAND(update_setupProgram), + COMMAND(update_setNoteSpacing), // 4 - COMMAND (update_jump), - COMMAND (update_jumpToSubroutine), - COMMAND (update_returnFromSubroutine), - COMMAND (update_setBaseOctave), + COMMAND(update_jump), + COMMAND(update_jumpToSubroutine), + COMMAND(update_returnFromSubroutine), + COMMAND(update_setBaseOctave), // 8 - COMMAND (update_stopChannel), - COMMAND (update_playRest), - COMMAND (update_writeAdlib), - COMMAND (update_setupNoteAndDuration), + COMMAND(update_stopChannel), + COMMAND(update_playRest), + COMMAND(update_writeAdlib), + COMMAND(update_setupNoteAndDuration), // 12 - COMMAND (update_setBaseNote), - COMMAND (update_setupSecondaryEffect1), - COMMAND (update_stopOtherChannel), - COMMAND (update_waitForEndOfProgram), + COMMAND(update_setBaseNote), + COMMAND(update_setupSecondaryEffect1), + COMMAND(update_stopOtherChannel), + COMMAND(update_waitForEndOfProgram), // 16 - COMMAND (update_setupInstrument), - COMMAND (update_setupPrimaryEffect1), - COMMAND (update_removePrimaryEffect1), - COMMAND (update_setBaseFreq), + COMMAND(update_setupInstrument), + COMMAND(update_setupPrimaryEffect1), + COMMAND(update_removePrimaryEffect1), + COMMAND(update_setBaseFreq), // 20 - COMMAND (update_stopChannel), - COMMAND (update_setupPrimaryEffect2), - COMMAND (update_stopChannel), - COMMAND (update_stopChannel), + COMMAND(update_stopChannel), + COMMAND(update_setupPrimaryEffect2), + COMMAND(update_stopChannel), + COMMAND(update_stopChannel), // 24 - COMMAND (update_stopChannel), - COMMAND (update_stopChannel), - COMMAND (update_setPriority), - COMMAND (update_stopChannel), + COMMAND(update_stopChannel), + COMMAND(update_stopChannel), + COMMAND(update_setPriority), + COMMAND(update_stopChannel), // 28 - COMMAND (updateCallback23), - COMMAND (updateCallback24), - COMMAND (update_setExtraLevel1), - COMMAND (update_stopChannel), + COMMAND(updateCallback23), + COMMAND(updateCallback24), + COMMAND(update_setExtraLevel1), + COMMAND(update_stopChannel), // 32 - COMMAND (update_setupDuration), - COMMAND (update_playNote), - COMMAND (update_stopChannel), - COMMAND (update_stopChannel), + COMMAND(update_setupDuration), + COMMAND(update_playNote), + COMMAND(update_stopChannel), + COMMAND(update_stopChannel), // 36 - COMMAND (update_setFractionalNoteSpacing), - COMMAND (update_stopChannel), - COMMAND (update_setTempo), - COMMAND (update_removeSecondaryEffect1), + COMMAND(update_setFractionalNoteSpacing), + COMMAND(update_stopChannel), + COMMAND(update_setTempo), + COMMAND(update_removeSecondaryEffect1), // 40 - COMMAND (update_stopChannel), - COMMAND (update_setChannelTempo), - COMMAND (update_stopChannel), - COMMAND (update_setExtraLevel3), + COMMAND(update_stopChannel), + COMMAND(update_setChannelTempo), + COMMAND(update_stopChannel), + COMMAND(update_setExtraLevel3), // 44 - COMMAND (update_setExtraLevel2), - COMMAND (update_changeExtraLevel2), - COMMAND (update_setAMDepth), - COMMAND (update_setVibratoDepth), + COMMAND(update_setExtraLevel2), + COMMAND(update_changeExtraLevel2), + COMMAND(update_setAMDepth), + COMMAND(update_setVibratoDepth), // 48 - COMMAND (update_changeExtraLevel1), - COMMAND (update_stopChannel), - COMMAND (update_stopChannel), - COMMAND (updateCallback38), + COMMAND(update_changeExtraLevel1), + COMMAND(update_stopChannel), + COMMAND(update_stopChannel), + COMMAND(updateCallback38), // 52 - COMMAND (update_stopChannel), - COMMAND (updateCallback39), - COMMAND (update_removePrimaryEffect2), - COMMAND (update_stopChannel), + COMMAND(update_stopChannel), + COMMAND(updateCallback39), + COMMAND(update_removePrimaryEffect2), + COMMAND(update_stopChannel), // 56 - COMMAND (update_stopChannel), - COMMAND (updateCallback41), - COMMAND (update_resetToGlobalTempo), - COMMAND (update_nop1), + COMMAND(update_stopChannel), + COMMAND(updateCallback41), + COMMAND(update_resetToGlobalTempo), + COMMAND(update_nop1), // 60 - COMMAND (update_setDurationRandomness), - COMMAND (update_changeChannelTempo), - COMMAND (update_stopChannel), - COMMAND (updateCallback46), + COMMAND(update_setDurationRandomness), + COMMAND(update_changeChannelTempo), + COMMAND(update_stopChannel), + COMMAND(updateCallback46), // 64 - COMMAND (update_nop2), - COMMAND (update_setupRhythmSection), - COMMAND (update_playRhythmSection), - COMMAND (update_removeRhythmSection), + COMMAND(update_nop2), + COMMAND(update_setupRhythmSection), + COMMAND(update_playRhythmSection), + COMMAND(update_removeRhythmSection), // 68 - COMMAND (updateCallback51), - COMMAND (updateCallback52), - COMMAND (updateCallback53), - COMMAND (update_setSoundTrigger), + COMMAND(updateCallback51), + COMMAND(updateCallback52), + COMMAND(updateCallback53), + COMMAND(update_setSoundTrigger), // 72 - COMMAND (update_setTempoReset), - COMMAND (updateCallback56), - COMMAND (update_stopChannel) + COMMAND(update_setTempoReset), + COMMAND(updateCallback56), + COMMAND(update_stopChannel) }; _parserOpcodeTable = parserOpcodeTable; - _parserOpcodeTableSize = ARRAYSIZE (parserOpcodeTable); + _parserOpcodeTableSize = ARRAYSIZE(parserOpcodeTable); } - #undef COMMAND // This table holds the register offset for operator 1 for each of the nine // channels. To get the register offset for operator 2, simply add 3. -const uint8 - AdlibDriver::_regOffset[] = { +const uint8 AdlibDriver::_regOffset[] = { 0x00, 0x01, 0x02, 0x08, 0x09, 0x0A, 0x10, 0x11, 0x12 }; @@ -2434,8 +2037,7 @@ const uint8 // F-Numbers (10 bits) for the notes of the 12-tone scale. However, it does not // match the table in the Adlib documentation I've seen. -const uint16 - AdlibDriver::_unkTable[] = { +const uint16 AdlibDriver::_unkTable[] = { 0x0134, 0x0147, 0x015A, 0x016F, 0x0184, 0x019C, 0x01B4, 0x01CE, 0x01E9, 0x0207, 0x0225, 0x0246 }; @@ -2443,8 +2045,7 @@ const uint16 // These tables are currently only used by updateCallback46(), which only ever // uses the first element of one of the sub-tables. -const uint8 * - AdlibDriver::_unkTable2[] = { +const uint8 *AdlibDriver::_unkTable2[] = { AdlibDriver::_unkTable2_1, AdlibDriver::_unkTable2_2, AdlibDriver::_unkTable2_1, @@ -2453,8 +2054,7 @@ const uint8 * AdlibDriver::_unkTable2_2 }; -const uint8 - AdlibDriver::_unkTable2_1[] = { +const uint8 AdlibDriver::_unkTable2_1[] = { 0x50, 0x50, 0x4F, 0x4F, 0x4E, 0x4E, 0x4D, 0x4D, 0x4C, 0x4C, 0x4B, 0x4B, 0x4A, 0x4A, 0x49, 0x49, 0x48, 0x48, 0x47, 0x47, 0x46, 0x46, 0x45, 0x45, @@ -2475,8 +2075,7 @@ const uint8 }; // no don't ask me WHY this table exsits! -const uint8 - AdlibDriver::_unkTable2_2[] = { +const uint8 AdlibDriver::_unkTable2_2[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, @@ -2495,8 +2094,7 @@ const uint8 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F }; -const uint8 - AdlibDriver::_unkTable2_3[] = { +const uint8 AdlibDriver::_unkTable2_3[] = { 0x40, 0x40, 0x40, 0x3F, 0x3F, 0x3F, 0x3E, 0x3E, 0x3E, 0x3D, 0x3D, 0x3D, 0x3C, 0x3C, 0x3C, 0x3B, 0x3B, 0x3B, 0x3A, 0x3A, 0x3A, 0x39, 0x39, 0x39, @@ -2523,78 +2121,77 @@ const uint8 // This could be some sort of pitch bend, but I have yet to see it used for // anything so it's hard to say. -const uint8 - AdlibDriver::_unkTables[][32] = { +const uint8 AdlibDriver::_unkTables[][32] = { // 0 - {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08, - 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, - 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x19, - 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21}, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x08, + 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x19, + 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21 }, // 1 - {0x00, 0x01, 0x02, 0x03, 0x04, 0x06, 0x07, 0x09, - 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, - 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x1A, - 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x22, 0x24}, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x06, 0x07, 0x09, + 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, + 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x1A, + 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x22, 0x24 }, // 2 - {0x00, 0x01, 0x02, 0x03, 0x04, 0x06, 0x08, 0x09, - 0x0A, 0x0C, 0x0D, 0x0E, 0x0F, 0x11, 0x12, 0x13, - 0x14, 0x15, 0x16, 0x17, 0x19, 0x1A, 0x1C, 0x1D, - 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x24, 0x25, 0x26}, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x06, 0x08, 0x09, + 0x0A, 0x0C, 0x0D, 0x0E, 0x0F, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x19, 0x1A, 0x1C, 0x1D, + 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x24, 0x25, 0x26 }, // 3 - {0x00, 0x01, 0x02, 0x03, 0x04, 0x06, 0x08, 0x0A, - 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x11, 0x12, 0x13, - 0x14, 0x15, 0x16, 0x17, 0x18, 0x1A, 0x1C, 0x1D, - 0x1E, 0x1F, 0x20, 0x21, 0x23, 0x25, 0x27, 0x28}, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x06, 0x08, 0x0A, + 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x18, 0x1A, 0x1C, 0x1D, + 0x1E, 0x1F, 0x20, 0x21, 0x23, 0x25, 0x27, 0x28 }, // 4 - {0x00, 0x01, 0x02, 0x03, 0x04, 0x06, 0x08, 0x0A, - 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x11, 0x13, 0x15, - 0x16, 0x17, 0x18, 0x19, 0x1B, 0x1D, 0x1F, 0x20, - 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x28, 0x2A}, + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x06, 0x08, 0x0A, + 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x11, 0x13, 0x15, + 0x16, 0x17, 0x18, 0x19, 0x1B, 0x1D, 0x1F, 0x20, + 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x28, 0x2A }, // 5 - {0x00, 0x01, 0x02, 0x03, 0x05, 0x07, 0x09, 0x0B, - 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x13, 0x15, - 0x16, 0x17, 0x18, 0x19, 0x1B, 0x1D, 0x1F, 0x20, - 0x21, 0x22, 0x23, 0x25, 0x27, 0x29, 0x2B, 0x2D}, + { 0x00, 0x01, 0x02, 0x03, 0x05, 0x07, 0x09, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x13, 0x15, + 0x16, 0x17, 0x18, 0x19, 0x1B, 0x1D, 0x1F, 0x20, + 0x21, 0x22, 0x23, 0x25, 0x27, 0x29, 0x2B, 0x2D }, // 6 - {0x00, 0x01, 0x02, 0x03, 0x05, 0x07, 0x09, 0x0B, - 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x13, 0x15, - 0x16, 0x17, 0x18, 0x1A, 0x1C, 0x1E, 0x21, 0x24, - 0x25, 0x26, 0x27, 0x29, 0x2B, 0x2D, 0x2F, 0x30}, + { 0x00, 0x01, 0x02, 0x03, 0x05, 0x07, 0x09, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x13, 0x15, + 0x16, 0x17, 0x18, 0x1A, 0x1C, 0x1E, 0x21, 0x24, + 0x25, 0x26, 0x27, 0x29, 0x2B, 0x2D, 0x2F, 0x30 }, // 7 - {0x00, 0x01, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, - 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x13, 0x15, 0x18, - 0x19, 0x1A, 0x1C, 0x1D, 0x1F, 0x21, 0x23, 0x25, - 0x26, 0x27, 0x29, 0x2B, 0x2D, 0x2F, 0x30, 0x32}, + { 0x00, 0x01, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, + 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x13, 0x15, 0x18, + 0x19, 0x1A, 0x1C, 0x1D, 0x1F, 0x21, 0x23, 0x25, + 0x26, 0x27, 0x29, 0x2B, 0x2D, 0x2F, 0x30, 0x32 }, // 8 - {0x00, 0x01, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0D, - 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x14, 0x17, 0x1A, - 0x19, 0x1A, 0x1C, 0x1E, 0x20, 0x22, 0x25, 0x28, - 0x29, 0x2A, 0x2B, 0x2D, 0x2F, 0x31, 0x33, 0x35}, + { 0x00, 0x01, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0D, + 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x14, 0x17, 0x1A, + 0x19, 0x1A, 0x1C, 0x1E, 0x20, 0x22, 0x25, 0x28, + 0x29, 0x2A, 0x2B, 0x2D, 0x2F, 0x31, 0x33, 0x35 }, // 9 - {0x00, 0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0E, - 0x0F, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1B, - 0x1C, 0x1D, 0x1E, 0x20, 0x22, 0x24, 0x26, 0x29, - 0x2A, 0x2C, 0x2E, 0x30, 0x32, 0x34, 0x36, 0x39}, + { 0x00, 0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0E, + 0x0F, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1A, 0x1B, + 0x1C, 0x1D, 0x1E, 0x20, 0x22, 0x24, 0x26, 0x29, + 0x2A, 0x2C, 0x2E, 0x30, 0x32, 0x34, 0x36, 0x39 }, // 10 - {0x00, 0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0E, - 0x0F, 0x10, 0x12, 0x14, 0x16, 0x19, 0x1B, 0x1E, - 0x1F, 0x21, 0x23, 0x25, 0x27, 0x29, 0x2B, 0x2D, - 0x2E, 0x2F, 0x31, 0x32, 0x34, 0x36, 0x39, 0x3C}, + { 0x00, 0x01, 0x03, 0x05, 0x07, 0x09, 0x0B, 0x0E, + 0x0F, 0x10, 0x12, 0x14, 0x16, 0x19, 0x1B, 0x1E, + 0x1F, 0x21, 0x23, 0x25, 0x27, 0x29, 0x2B, 0x2D, + 0x2E, 0x2F, 0x31, 0x32, 0x34, 0x36, 0x39, 0x3C }, // 11 - {0x00, 0x01, 0x03, 0x05, 0x07, 0x0A, 0x0C, 0x0F, - 0x10, 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1E, - 0x1F, 0x20, 0x22, 0x24, 0x26, 0x28, 0x2B, 0x2E, - 0x2F, 0x30, 0x32, 0x34, 0x36, 0x39, 0x3C, 0x3F}, + { 0x00, 0x01, 0x03, 0x05, 0x07, 0x0A, 0x0C, 0x0F, + 0x10, 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1E, + 0x1F, 0x20, 0x22, 0x24, 0x26, 0x28, 0x2B, 0x2E, + 0x2F, 0x30, 0x32, 0x34, 0x36, 0x39, 0x3C, 0x3F }, // 12 - {0x00, 0x02, 0x04, 0x06, 0x08, 0x0B, 0x0D, 0x10, - 0x11, 0x12, 0x14, 0x16, 0x18, 0x1B, 0x1E, 0x21, - 0x22, 0x23, 0x25, 0x27, 0x29, 0x2C, 0x2F, 0x32, - 0x33, 0x34, 0x36, 0x38, 0x3B, 0x34, 0x41, 0x44}, + { 0x00, 0x02, 0x04, 0x06, 0x08, 0x0B, 0x0D, 0x10, + 0x11, 0x12, 0x14, 0x16, 0x18, 0x1B, 0x1E, 0x21, + 0x22, 0x23, 0x25, 0x27, 0x29, 0x2C, 0x2F, 0x32, + 0x33, 0x34, 0x36, 0x38, 0x3B, 0x34, 0x41, 0x44 }, // 13 - {0x00, 0x02, 0x04, 0x06, 0x08, 0x0B, 0x0D, 0x11, - 0x12, 0x13, 0x15, 0x17, 0x1A, 0x1D, 0x20, 0x23, - 0x24, 0x25, 0x27, 0x29, 0x2C, 0x2F, 0x32, 0x35, - 0x36, 0x37, 0x39, 0x3B, 0x3E, 0x41, 0x44, 0x47} + { 0x00, 0x02, 0x04, 0x06, 0x08, 0x0B, 0x0D, 0x11, + 0x12, 0x13, 0x15, 0x17, 0x1A, 0x1D, 0x20, 0x23, + 0x24, 0x25, 0x27, 0x29, 0x2C, 0x2F, 0x32, 0x35, + 0x36, 0x37, 0x39, 0x3B, 0x3E, 0x41, 0x44, 0x47 } }; // #pragma mark - @@ -2602,21 +2199,18 @@ const uint8 // At the time of writing, the only known case where Kyra 1 uses sound triggers // is in the castle, to cycle between three different songs. -const int - CadlPlayer::_kyra1SoundTriggers[] = { +const int CadlPlayer::_kyra1SoundTriggers[] = { 0, 4, 5, 3 }; -const int - CadlPlayer::_kyra1NumSoundTriggers = -ARRAYSIZE (CadlPlayer::_kyra1SoundTriggers); +const int CadlPlayer::_kyra1NumSoundTriggers = ARRAYSIZE(CadlPlayer::_kyra1SoundTriggers); -CadlPlayer::CadlPlayer (Copl * newopl):CPlayer (newopl), numsubsongs (0), _trackEntries (), -_soundDataPtr (0) +CadlPlayer::CadlPlayer(Copl *newopl) + : CPlayer(newopl), numsubsongs(0), _trackEntries(), _soundDataPtr(0) { - memset (_trackEntries, 0, sizeof (_trackEntries)); - _driver = new AdlibDriver (newopl); - assert (_driver); + memset(_trackEntries, 0, sizeof(_trackEntries)); + _driver = new AdlibDriver(newopl); + assert(_driver); _sfxPlayingSound = -1; // _soundFileLoaded = ""; @@ -2624,42 +2218,31 @@ _soundDataPtr (0) _soundTriggers = _kyra1SoundTriggers; _numSoundTriggers = _kyra1NumSoundTriggers; - init (); + init(); } -CadlPlayer::~CadlPlayer () -{ - delete[]_soundDataPtr; - _soundDataPtr = 0; +CadlPlayer::~CadlPlayer() { + delete [] _soundDataPtr; delete _driver; - _driver = 0; } -bool -CadlPlayer::init () -{ - _driver->callback (2); - _driver->callback (16, int (4)); +bool CadlPlayer::init() { + _driver->callback(2); + _driver->callback(16, int(4)); return true; } -void -CadlPlayer::process () -{ - uint8 trigger = _driver->callback (11); +void CadlPlayer::process() { + uint8 trigger = _driver->callback(11); - if (trigger < _numSoundTriggers) - { + if (trigger < _numSoundTriggers) { int soundId = _soundTriggers[trigger]; - if (soundId) - { - playTrack (soundId); + if (soundId) { + playTrack(soundId); } - } - else - { - warning ("Unknown sound trigger %d", trigger); + } else { + warning("Unknown sound trigger %d", trigger); // TODO: At this point, we really want to clear the trigger... } } @@ -2668,59 +2251,50 @@ CadlPlayer::process () // } // int CadlPlayer::getVolume() { -// return 0; +// return 0; // } // void CadlPlayer::loadMusicFile(const char *file) { -// loadSoundFile(file); +// loadSoundFile(file); // } -void -CadlPlayer::playTrack (uint8 track) -{ - play (track); +void CadlPlayer::playTrack(uint8 track) { + play(track); } // void CadlPlayer::haltTrack() { -// unk1(); -// unk2(); -// //_engine->_system->delayMillis(3 * 60); +// unk1(); +// unk2(); +// //_engine->_system->delayMillis(3 * 60); // } -void -CadlPlayer::playSoundEffect (uint8_t track) -{ - play (track); +void CadlPlayer::playSoundEffect(uint8_t track) { + play(track); } -void -CadlPlayer::play (uint8_t track) -{ +void CadlPlayer::play(uint8_t track) { uint8 soundId = _trackEntries[track]; - if ((int8) soundId == -1 || !_soundDataPtr) + if ((int8)soundId == -1 || !_soundDataPtr) return; soundId &= 0xFF; - _driver->callback (16, 0); + _driver->callback(16, 0); // while ((_driver->callback(16, 0) & 8)) { // We call the system delay and not the game delay to avoid concurrency issues. - // _engine->_system->delayMillis(10); + // _engine->_system->delayMillis(10); // } - if (_sfxPlayingSound != -1) - { + if (_sfxPlayingSound != -1) { // Restore the sounds's normal values. - _driver->callback (10, _sfxPlayingSound, int (1), int (_sfxPriority)); - _driver->callback (10, _sfxPlayingSound, int (3), - int (_sfxFourthByteOfSong)); + _driver->callback(10, _sfxPlayingSound, int(1), int(_sfxPriority)); + _driver->callback(10, _sfxPlayingSound, int(3), int(_sfxFourthByteOfSong)); _sfxPlayingSound = -1; } - int chan = _driver->callback (9, soundId, int (0)); + int chan = _driver->callback(9, soundId, int(0)); - if (chan != 9) - { + if (chan != 9) { _sfxPlayingSound = soundId; - _sfxPriority = _driver->callback (9, soundId, int (1)); - _sfxFourthByteOfSong = _driver->callback (9, soundId, int (3)); + _sfxPriority = _driver->callback(9, soundId, int(1)); + _sfxFourthByteOfSong = _driver->callback(9, soundId, int(3)); // In the cases I've seen, the mysterious fourth byte has been // the parameter for the update_setExtraLevel3() callback. @@ -2735,76 +2309,72 @@ CadlPlayer::play (uint8_t track) int newVal = ((((-_sfxFourthByteOfSong) + 63) * 0xFF) >> 8) & 0xFF; newVal = -newVal + 63; - _driver->callback (10, soundId, int (3), newVal); + _driver->callback(10, soundId, int(3), newVal); newVal = ((_sfxPriority * 0xFF) >> 8) & 0xFF; - _driver->callback (10, soundId, int (1), newVal); + _driver->callback(10, soundId, int(1), newVal); } - _driver->callback (6, soundId); + _driver->callback(6, soundId); } // void CadlPlayer::beginFadeOut() { -// playSoundEffect(1); +// playSoundEffect(1); // } -bool -CadlPlayer::load (VFSFile & fd, const CFileProvider & fp) +bool CadlPlayer::load(const std::string &filename, const CFileProvider &fp) { - binistream *f = fp.open (fd); - std::string filename (fd.filename ()); + binistream *f = fp.open(filename); // file validation section - if (!f || !fp.extension (filename, ".adl")) - { - fp.close (f); + if(!f || !fp.extension(filename, ".adl")) { + fp.close(f); return false; } // if (_soundFileLoaded == file) - // return; + // return; // if (_soundDataPtr) { - // haltTrack(); + // haltTrack(); // } - uint8 *file_data = 0; - uint32 file_size = 0; + uint8 *file_data = 0; uint32 file_size = 0; // char filename[25]; // sprintf(filename, "%s.ADL", file); // file_data = _engine->resource()->fileData(filename, &file_size); // if (!file_data) { - // warning("Couldn't find music file: '%s'", filename); - // return; + // warning("Couldn't find music file: '%s'", filename); + // return; // } - unk2 (); - unk1 (); + unk2(); + unk1(); - file_size = fp.filesize (f); - file_data = new uint8[file_size]; - f->readString ((char *) file_data, file_size); + file_size = fp.filesize(f); + file_data = new uint8 [file_size]; + f->readString((char *)file_data, file_size); - _driver->callback (8, int (-1)); + _driver->callback(8, int(-1)); _soundDataPtr = 0; uint8 *p = file_data; - memcpy (_trackEntries, p, 120 * sizeof (uint8)); + memcpy(_trackEntries, p, 120*sizeof(uint8)); p += 120; int soundDataSize = file_size - 120; _soundDataPtr = new uint8[soundDataSize]; - assert (_soundDataPtr); + assert(_soundDataPtr); - memcpy (_soundDataPtr, p, soundDataSize * sizeof (uint8)); + memcpy(_soundDataPtr, p, soundDataSize*sizeof(uint8)); - delete[]file_data; + delete [] file_data; file_data = p = 0; file_size = 0; - _driver->callback (4, _soundDataPtr); + _driver->callback(4, _soundDataPtr); // _soundFileLoaded = file; @@ -2814,61 +2384,54 @@ CadlPlayer::load (VFSFile & fd, const CFileProvider & fp) numsubsongs = i + 1; break; } - fp.close (f); + + fp.close(f); cursubsong = 2; rewind(); return true; } -void -CadlPlayer::rewind (int subsong) +void CadlPlayer::rewind(int subsong) { if(subsong == -1) subsong = cursubsong; - opl->init (); - opl->write (1, 32); - playSoundEffect (subsong); + opl->init(); + opl->write(1,32); + playSoundEffect(subsong); cursubsong = subsong; - update (); + update(); } -unsigned int -CadlPlayer::getsubsongs () +unsigned int CadlPlayer::getsubsongs() { return numsubsongs; } -bool -CadlPlayer::update () +bool CadlPlayer::update() { bool songend = true; // if(_trackEntries[cursubsong] == 0xff) // return false; - _driver->callback (); + _driver->callback(); - for (int i = 0; i < 10; i++) - if (_driver->_channels[i].dataptr != nullptr) + for(int i = 0; i < 10; i++) + if(_driver->_channels[i].dataptr != NULL) songend = false; return !songend; } -void -CadlPlayer::unk1 () -{ - playSoundEffect (0); +void CadlPlayer::unk1() { + playSoundEffect(0); //_engine->_system->delayMillis(5 * 60); } -void -CadlPlayer::unk2 () -{ - playSoundEffect (0); +void CadlPlayer::unk2() { + playSoundEffect(0); } -CPlayer * -CadlPlayer::factory (Copl * newopl) +CPlayer *CadlPlayer::factory(Copl *newopl) { - return new CadlPlayer (newopl); + return new CadlPlayer(newopl); } diff --git a/src/adplug/core/adl.h b/src/adplug/core/adl.h index fc3b1f2..dd5e55d 100644 --- a/src/adplug/core/adl.h +++ b/src/adplug/core/adl.h @@ -14,7 +14,7 @@ * * 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 Street, Fifth Floor, Boston, MA 02110-1301, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * adl.h - ADL player adaption by Simon Peter <dn.tlp@gmx.net> */ @@ -36,7 +36,7 @@ class CadlPlayer: public CPlayer CadlPlayer(Copl *newopl); ~CadlPlayer(); - bool load(VFSFile &fd, const CFileProvider &fp); + bool load(const std::string &filename, const CFileProvider &fp); bool update(); void rewind(int subsong = -1); diff --git a/src/adplug/core/adlibemu.cc b/src/adplug/core/adlibemu.cc index ee3ad93..a5ecf36 100644 --- a/src/adplug/core/adlibemu.cc +++ b/src/adplug/core/adlibemu.cc @@ -51,6 +51,9 @@ I'm not sure about a few things in my code: #include <string.h> #include <algorithm> +using std::max; +using std::min; + #define PI 3.141592653589793 #define MAXCELLS 18 #define WAVPREC 2048 @@ -97,7 +100,7 @@ long rplc[9] = {0,0,0,0,0,0,0,0,0}; //Samples to delay on right speaker long nlvol[9], nrvol[9]; long nlplc[9], nrplc[9]; long rend = 0; -#define FIFOSIZ 256 +#define FIFOSIZ 256L static float *rptr[9], *nrptr[9]; static float rbuf[9][FIFOSIZ*2]; static float snd[FIFOSIZ*2]; @@ -110,11 +113,11 @@ static float snd[FIFOSIZ*2]; static _inline void ftol (float f, long *a) { _asm - { - mov eax, a - fld f - fistp dword ptr [eax] - } + { + mov eax, a + fld f + fistp dword ptr [eax] + } } #else static void ftol(float f, long *a) { @@ -140,8 +143,8 @@ void docell2 (void *c, float modulator) if ((long)ctc->amp <= 0x37800000) { - ctc->amp = 0; - ctc->cellfunc = docell4; + ctc->amp = 0; + ctc->cellfunc = docell4; } ctc->amp *= ctc->releasemul; @@ -156,16 +159,16 @@ void docell1 (void *c, float modulator) if ((long)ctc->amp <= (long)ctc->sustain) { - if (ctc->flags&32) - { - ctc->amp = ctc->sustain; - ctc->cellfunc = docell3; - } - else - ctc->cellfunc = docell2; + if (ctc->flags&32) + { + ctc->amp = ctc->sustain; + ctc->cellfunc = docell3; + } + else + ctc->cellfunc = docell2; } else - ctc->amp *= ctc->decaymul; + ctc->amp *= ctc->decaymul; ctc->t += ctc->tinc; ctc->val += (ctc->amp*ctc->vol*((float)ctc->waveform[i&ctc->wavemask])-ctc->val)*ADJUSTSPEED; @@ -179,8 +182,8 @@ void docell0 (void *c, float modulator) ctc->amp = ((ctc->a3*ctc->amp + ctc->a2)*ctc->amp + ctc->a1)*ctc->amp + ctc->a0; if ((long)ctc->amp > 0x3f800000) { - ctc->amp = 1; - ctc->cellfunc = docell1; + ctc->amp = 1; + ctc->cellfunc = docell1; } ctc->t += ctc->tinc; @@ -216,7 +219,7 @@ void cellon (long i, long j, celltype *c, unsigned char iscarrier) c->cellfunc = docell0; c->tinc = (float)(frn<<oct)*nfrqmul[adlibreg[j+0x20]&15]; c->vol = pow(2.0,((float)(adlibreg[j+0x40]&63) + - (float)kslmul[adlibreg[j+0x40]>>6]*ksl[oct][frn>>6]) * -.125 - 14); + (float)kslmul[adlibreg[j+0x40]>>6]*ksl[oct][frn>>6]) * -.125 - 14); c->sustain = pow(2.0,(float)(adlibreg[j+0x80]>>4) * -.5); if (!iscarrier) c->amp = 0; c->mfb = pow(2.0,((adlibreg[i+0xc0]>>1)&7)+5)*(WAVPREC/2048.0)*MFBFACTOR; @@ -234,7 +237,7 @@ void cellfreq (signed long i, signed long j, celltype *c) c->tinc = (float)(frn<<oct)*nfrqmul[adlibreg[j+0x20]&15]; c->vol = pow(2.0,((float)(adlibreg[j+0x40]&63) + - (float)kslmul[adlibreg[j+0x40]>>6]*ksl[oct][frn>>6]) * -.125 - 14); + (float)kslmul[adlibreg[j+0x40]>>6]*ksl[oct][frn>>6]) * -.125 - 14); } static long initfirstime = 0; @@ -249,13 +252,13 @@ void adlibinit (long dasamplerate, long danumspeakers, long dabytespersample) for(i=0;i<MAXCELLS;i++) { - cell[i].cellfunc = docell4; - cell[i].amp = 0; - cell[i].vol = 0; - cell[i].t = 0; - cell[i].tinc = 0; - cell[i].wavemask = 0; - cell[i].waveform = &wavtable[WAVPREC]; + cell[i].cellfunc = docell4; + cell[i].amp = 0; + cell[i].vol = 0; + cell[i].t = 0; + cell[i].tinc = 0; + cell[i].wavemask = 0; + cell[i].waveform = &wavtable[WAVPREC]; } numspeakers = danumspeakers; @@ -266,39 +269,39 @@ void adlibinit (long dasamplerate, long danumspeakers, long dabytespersample) if (!initfirstime) { - initfirstime = 1; - - for(i=0;i<(WAVPREC>>1);i++) - { - wavtable[i] = - wavtable[(i<<1) +WAVPREC] = (signed short)(16384*sin((float)((i<<1) )*PI*2/WAVPREC)); - wavtable[(i<<1)+1+WAVPREC] = (signed short)(16384*sin((float)((i<<1)+1)*PI*2/WAVPREC)); - } - for(i=0;i<(WAVPREC>>3);i++) - { - wavtable[i+(WAVPREC<<1)] = wavtable[i+(WAVPREC>>3)]-16384; - wavtable[i+((WAVPREC*17)>>3)] = wavtable[i+(WAVPREC>>2)]+16384; - } - - //[table in book]*8/3 - ksl[7][0] = 0; ksl[7][1] = 24; ksl[7][2] = 32; ksl[7][3] = 37; - ksl[7][4] = 40; ksl[7][5] = 43; ksl[7][6] = 45; ksl[7][7] = 47; - ksl[7][8] = 48; for(i=9;i<16;i++) ksl[7][i] = i+41; - for(j=6;j>=0;j--) - for(i=0;i<16;i++) - { - oct = (long)ksl[j+1][i]-8; if (oct < 0) oct = 0; - ksl[j][i] = (unsigned char)oct; - } + initfirstime = 1; + + for(i=0;i<(WAVPREC>>1);i++) + { + wavtable[i] = + wavtable[(i<<1) +WAVPREC] = (signed short)(16384*sin((float)((i<<1) )*PI*2/WAVPREC)); + wavtable[(i<<1)+1+WAVPREC] = (signed short)(16384*sin((float)((i<<1)+1)*PI*2/WAVPREC)); + } + for(i=0;i<(WAVPREC>>3);i++) + { + wavtable[i+(WAVPREC<<1)] = wavtable[i+(WAVPREC>>3)]-16384; + wavtable[i+((WAVPREC*17)>>3)] = wavtable[i+(WAVPREC>>2)]+16384; + } + + //[table in book]*8/3 + ksl[7][0] = 0; ksl[7][1] = 24; ksl[7][2] = 32; ksl[7][3] = 37; + ksl[7][4] = 40; ksl[7][5] = 43; ksl[7][6] = 45; ksl[7][7] = 47; + ksl[7][8] = 48; for(i=9;i<16;i++) ksl[7][i] = i+41; + for(j=6;j>=0;j--) + for(i=0;i<16;i++) + { + oct = (long)ksl[j+1][i]-8; if (oct < 0) oct = 0; + ksl[j][i] = (unsigned char)oct; + } } else { - for(i=0;i<9;i++) - { - frn = ((((long)adlibreg[i+0xb0])&3)<<8) + (long)adlibreg[i+0xa0]; - oct = ((((long)adlibreg[i+0xb0])>>2)&7); - cell[i].tinc = (float)(frn<<oct)*nfrqmul[adlibreg[modulatorbase[i]+0x20]&15]; - } + for(i=0;i<9;i++) + { + frn = ((((long)adlibreg[i+0xb0])&3)<<8) + (long)adlibreg[i+0xa0]; + oct = ((((long)adlibreg[i+0xb0])>>2)&7); + cell[i].tinc = (float)(frn<<oct)*nfrqmul[adlibreg[modulatorbase[i]+0x20]&15]; + } } } @@ -309,71 +312,71 @@ void adlib0 (long i, long v) if (i == 0xbd) { - if ((v&16) > (odrumstat&16)) //BassDrum - { - cellon(6,16,&cell[6],0); - cellon(6,19,&cell[15],1); - cell[15].vol *= 2; - } - if ((v&8) > (odrumstat&8)) //Snare - { - cellon(16,20,&cell[16],0); - cell[16].tinc *= 2*(nfrqmul[adlibreg[17+0x20]&15] / nfrqmul[adlibreg[20+0x20]&15]); - if (((adlibreg[20+0xe0]&7) >= 3) && ((adlibreg[20+0xe0]&7) <= 5)) cell[16].vol = 0; - cell[16].vol *= 2; - } - if ((v&4) > (odrumstat&4)) //TomTom - { - cellon(8,18,&cell[8],0); - cell[8].vol *= 2; - } - if ((v&2) > (odrumstat&2)) //Cymbal - { - cellon(17,21,&cell[17],0); - - cell[17].wavemask = wavemask[5]; - cell[17].waveform = &wavtable[waveform[5]]; - cell[17].tinc *= 16; cell[17].vol *= 2; - - //cell[17].waveform = &wavtable[WAVPREC]; cell[17].wavemask = 0; - //if (((adlibreg[21+0xe0]&7) == 0) || ((adlibreg[21+0xe0]&7) == 6)) - // cell[17].waveform = &wavtable[(WAVPREC*7)>>2]; - //if (((adlibreg[21+0xe0]&7) == 2) || ((adlibreg[21+0xe0]&7) == 3)) - // cell[17].waveform = &wavtable[(WAVPREC*5)>>2]; - } - if ((v&1) > (odrumstat&1)) //Hihat - { - cellon(7,17,&cell[7],0); - if (((adlibreg[17+0xe0]&7) == 1) || ((adlibreg[17+0xe0]&7) == 4) || - ((adlibreg[17+0xe0]&7) == 5) || ((adlibreg[17+0xe0]&7) == 7)) cell[7].vol = 0; - if ((adlibreg[17+0xe0]&7) == 6) { cell[7].wavemask = 0; cell[7].waveform = &wavtable[(WAVPREC*7)>>2]; } - } - - odrumstat = v; + if ((v&16) > (odrumstat&16)) //BassDrum + { + cellon(6,16,&cell[6],0); + cellon(6,19,&cell[15],1); + cell[15].vol *= 2; + } + if ((v&8) > (odrumstat&8)) //Snare + { + cellon(16,20,&cell[16],0); + cell[16].tinc *= 2*(nfrqmul[adlibreg[17+0x20]&15] / nfrqmul[adlibreg[20+0x20]&15]); + if (((adlibreg[20+0xe0]&7) >= 3) && ((adlibreg[20+0xe0]&7) <= 5)) cell[16].vol = 0; + cell[16].vol *= 2; + } + if ((v&4) > (odrumstat&4)) //TomTom + { + cellon(8,18,&cell[8],0); + cell[8].vol *= 2; + } + if ((v&2) > (odrumstat&2)) //Cymbal + { + cellon(17,21,&cell[17],0); + + cell[17].wavemask = wavemask[5]; + cell[17].waveform = &wavtable[waveform[5]]; + cell[17].tinc *= 16; cell[17].vol *= 2; + + //cell[17].waveform = &wavtable[WAVPREC]; cell[17].wavemask = 0; + //if (((adlibreg[21+0xe0]&7) == 0) || ((adlibreg[21+0xe0]&7) == 6)) + // cell[17].waveform = &wavtable[(WAVPREC*7)>>2]; + //if (((adlibreg[21+0xe0]&7) == 2) || ((adlibreg[21+0xe0]&7) == 3)) + // cell[17].waveform = &wavtable[(WAVPREC*5)>>2]; + } + if ((v&1) > (odrumstat&1)) //Hihat + { + cellon(7,17,&cell[7],0); + if (((adlibreg[17+0xe0]&7) == 1) || ((adlibreg[17+0xe0]&7) == 4) || + ((adlibreg[17+0xe0]&7) == 5) || ((adlibreg[17+0xe0]&7) == 7)) cell[7].vol = 0; + if ((adlibreg[17+0xe0]&7) == 6) { cell[7].wavemask = 0; cell[7].waveform = &wavtable[(WAVPREC*7)>>2]; } + } + + odrumstat = v; } else if (((unsigned)(i-0x40) < (unsigned)22) && ((i&7) < 6)) { - if ((i&7) < 3) // Modulator - cellfreq(base2cell[i-0x40],i-0x40,&cell[base2cell[i-0x40]]); - else // Carrier - cellfreq(base2cell[i-0x40],i-0x40,&cell[base2cell[i-0x40]+9]); + if ((i&7) < 3) // Modulator + cellfreq(base2cell[i-0x40],i-0x40,&cell[base2cell[i-0x40]]); + else // Carrier + cellfreq(base2cell[i-0x40],i-0x40,&cell[base2cell[i-0x40]+9]); } else if ((unsigned)(i-0xa0) < (unsigned)9) { - cellfreq(i-0xa0,modulatorbase[i-0xa0],&cell[i-0xa0]); - cellfreq(i-0xa0,modulatorbase[i-0xa0]+3,&cell[i-0xa0+9]); + cellfreq(i-0xa0,modulatorbase[i-0xa0],&cell[i-0xa0]); + cellfreq(i-0xa0,modulatorbase[i-0xa0]+3,&cell[i-0xa0+9]); } else if ((unsigned)(i-0xb0) < (unsigned)9) { - if ((v&32) > (tmp&32)) - { - cellon(i-0xb0,modulatorbase[i-0xb0],&cell[i-0xb0],0); - cellon(i-0xb0,modulatorbase[i-0xb0]+3,&cell[i-0xb0+9],1); - } - else if ((v&32) < (tmp&32)) - cell[i-0xb0].cellfunc = cell[i-0xb0+9].cellfunc = docell2; - cellfreq(i-0xb0,modulatorbase[i-0xb0],&cell[i-0xb0]); - cellfreq(i-0xb0,modulatorbase[i-0xb0]+3,&cell[i-0xb0+9]); + if ((v&32) > (tmp&32)) + { + cellon(i-0xb0,modulatorbase[i-0xb0],&cell[i-0xb0],0); + cellon(i-0xb0,modulatorbase[i-0xb0]+3,&cell[i-0xb0+9],1); + } + else if ((v&32) < (tmp&32)) + cell[i-0xb0].cellfunc = cell[i-0xb0+9].cellfunc = docell2; + cellfreq(i-0xb0,modulatorbase[i-0xb0],&cell[i-0xb0]); + cellfreq(i-0xb0,modulatorbase[i-0xb0]+3,&cell[i-0xb0+9]); } //outdata(i,v); @@ -385,34 +388,34 @@ static float fakeadd = 8388608.0+128.0; static _inline void clipit8 (float f, long a) { _asm - { - mov edi, a - fld dword ptr f - fadd dword ptr fakeadd - fstp dword ptr fpuasm - mov eax, fpuasm - test eax, 0x007fff00 - jz short skipit - shr eax, 16 - xor eax, -1 - skipit: mov byte ptr [edi], al - } + { + mov edi, a + fld dword ptr f + fadd dword ptr fakeadd + fstp dword ptr fpuasm + mov eax, fpuasm + test eax, 0x007fff00 + jz short skipit + shr eax, 16 + xor eax, -1 + skipit: mov byte ptr [edi], al + } } static _inline void clipit16 (float f, long a) { _asm - { - mov eax, a - fld dword ptr f - fist word ptr [eax] - cmp word ptr [eax], 0x8000 - jne short skipit2 - fst dword ptr [fpuasm] - cmp fpuasm, 0x80000000 - sbb word ptr [eax], 0 - skipit2: fstp st - } + { + mov eax, a + fld dword ptr f + fist word ptr [eax] + cmp word ptr [eax], 0x8000 + jne short skipit2 + fst dword ptr [fpuasm] + cmp fpuasm, 0x80000000 + sbb word ptr [eax], 0 + skipit2: fstp st + } } #else static void clipit8(float f,unsigned char *a) { @@ -446,26 +449,26 @@ void adlibgetsample (unsigned char *sndptr, long numbytes) if (bytespersample == 1) f = AMPSCALE/256.0; else f = AMPSCALE; if (numspeakers == 1) { - nlvol[0] = lvol[0]*f; - for(i=0;i<9;i++) rptr[i] = &rbuf[0][0]; - rptrs = 1; + nlvol[0] = lvol[0]*f; + for(i=0;i<9;i++) rptr[i] = &rbuf[0][0]; + rptrs = 1; } else { - rptrs = 0; - for(i=0;i<9;i++) - { - if ((!i) || (lvol[i] != lvol[i-1]) || (rvol[i] != rvol[i-1]) || - (lplc[i] != lplc[i-1]) || (rplc[i] != rplc[i-1])) - { - nlvol[rptrs] = lvol[i]*f; - nrvol[rptrs] = rvol[i]*f; - nlplc[rptrs] = rend-std::min(std::max(lplc[i],0L),(long)FIFOSIZ); - nrplc[rptrs] = rend-std::min(std::max(rplc[i],0L),(long)FIFOSIZ); - rptrs++; - } - rptr[i] = &rbuf[rptrs-1][0]; - } + rptrs = 0; + for(i=0;i<9;i++) + { + if ((!i) || (lvol[i] != lvol[i-1]) || (rvol[i] != rvol[i-1]) || + (lplc[i] != lplc[i-1]) || (rplc[i] != rplc[i-1])) + { + nlvol[rptrs] = lvol[i]*f; + nrvol[rptrs] = rvol[i]*f; + nlplc[rptrs] = rend-min(max(lplc[i],0L),FIFOSIZ); + nrplc[rptrs] = rend-min(max(rplc[i],0L),FIFOSIZ); + rptrs++; + } + rptr[i] = &rbuf[rptrs-1][0]; + } } @@ -474,121 +477,121 @@ void adlibgetsample (unsigned char *sndptr, long numbytes) for(ns=0;ns<numsamples;ns+=endsamples) { - endsamples = std::min(FIFOSIZ*2-rend,(long)FIFOSIZ); - endsamples = std::min(endsamples,numsamples-ns); - - for(i=0;i<9;i++) - nrptr[i] = &rptr[i][rend]; - for(i=0;i<rptrs;i++) - memset((void *)&rbuf[i][rend],0,endsamples*sizeof(float)); - - if (adlibreg[0xbd]&0x20) - { - //BassDrum (j=6) - if (cell[15].cellfunc != docell4) - { - if (adlibreg[0xc6]&1) - { - for(i=0;i<endsamples;i++) - { - (cell[15].cellfunc)((void *)&cell[15],0.0); - nrptr[6][i] += cell[15].val; - } - } - else - { - for(i=0;i<endsamples;i++) - { - (cell[6].cellfunc)((void *)&cell[6],cell[6].val*cell[6].mfb); - (cell[15].cellfunc)((void *)&cell[15],cell[6].val*WAVPREC*MODFACTOR); - nrptr[6][i] += cell[15].val; - } - } - } - - //Snare/Hihat (j=7), Cymbal/TomTom (j=8) - if ((cell[7].cellfunc != docell4) || (cell[8].cellfunc != docell4) || (cell[16].cellfunc != docell4) || (cell[17].cellfunc != docell4)) - { - for(i=0;i<endsamples;i++) - { - k = k*1664525+1013904223; - (cell[16].cellfunc)((void *)&cell[16],k&((WAVPREC>>1)-1)); //Snare - (cell[7].cellfunc)((void *)&cell[7],k&(WAVPREC-1)); //Hihat - (cell[17].cellfunc)((void *)&cell[17],k&((WAVPREC>>3)-1)); //Cymbal - (cell[8].cellfunc)((void *)&cell[8],0.0); //TomTom - nrptr[7][i] += cell[7].val + cell[16].val; - nrptr[8][i] += cell[8].val + cell[17].val; - } - } - } - for(j=9-1;j>=0;j--) - { - if ((adlibreg[0xbd]&0x20) && (j >= 6) && (j < 9)) continue; - - cptr = &cell[j]; k = j; - if (adlibreg[0xc0+k]&1) - { - if ((cptr[9].cellfunc == docell4) && (cptr->cellfunc == docell4)) continue; - for(i=0;i<endsamples;i++) - { - (cptr->cellfunc)((void *)cptr,cptr->val*cptr->mfb); - (cptr->cellfunc)((void *)&cptr[9],0); - nrptr[j][i] += cptr[9].val + cptr->val; - } - } - else - { - if (cptr[9].cellfunc == docell4) continue; - for(i=0;i<endsamples;i++) - { - (cptr->cellfunc)((void *)cptr,cptr->val*cptr->mfb); - (cptr[9].cellfunc)((void *)&cptr[9],cptr->val*WAVPREC*MODFACTOR); - nrptr[j][i] += cptr[9].val; - } - } - } - - if (numspeakers == 1) - { - if (bytespersample == 1) - { - for(i=endsamples-1;i>=0;i--) - clipit8(nrptr[0][i]*nlvol[0],sndptr+1); - } - else - { - for(i=endsamples-1;i>=0;i--) - clipit16(nrptr[0][i]*nlvol[0],sndptr2+i); - } - } - else - { - memset((void *)snd,0,endsamples*sizeof(float)*2); - for(j=0;j<rptrs;j++) - { - for(i=0;i<endsamples;i++) - { - snd[(i<<1) ] += rbuf[j][(nlplc[j]+i)&(FIFOSIZ*2-1)]*nlvol[j]; - snd[(i<<1)+1] += rbuf[j][(nrplc[j]+i)&(FIFOSIZ*2-1)]*nrvol[j]; - } - nlplc[j] += endsamples; - nrplc[j] += endsamples; - } - - if (bytespersample == 1) - { - for(i=(endsamples<<1)-1;i>=0;i--) - clipit8(snd[i],sndptr+i); - } - else - { - for(i=(endsamples<<1)-1;i>=0;i--) - clipit16(snd[i],sndptr2+i); - } - } - - sndptr = sndptr+(numspeakers*endsamples); - sndptr2 = sndptr2+(numspeakers*endsamples); - rend = ((rend+endsamples)&(FIFOSIZ*2-1)); + endsamples = min(FIFOSIZ*2-rend,FIFOSIZ); + endsamples = min(endsamples,numsamples-ns); + + for(i=0;i<9;i++) + nrptr[i] = &rptr[i][rend]; + for(i=0;i<rptrs;i++) + memset((void *)&rbuf[i][rend],0,endsamples*sizeof(float)); + + if (adlibreg[0xbd]&0x20) + { + //BassDrum (j=6) + if (cell[15].cellfunc != docell4) + { + if (adlibreg[0xc6]&1) + { + for(i=0;i<endsamples;i++) + { + (cell[15].cellfunc)((void *)&cell[15],0.0); + nrptr[6][i] += cell[15].val; + } + } + else + { + for(i=0;i<endsamples;i++) + { + (cell[6].cellfunc)((void *)&cell[6],cell[6].val*cell[6].mfb); + (cell[15].cellfunc)((void *)&cell[15],cell[6].val*WAVPREC*MODFACTOR); + nrptr[6][i] += cell[15].val; + } + } + } + + //Snare/Hihat (j=7), Cymbal/TomTom (j=8) + if ((cell[7].cellfunc != docell4) || (cell[8].cellfunc != docell4) || (cell[16].cellfunc != docell4) || (cell[17].cellfunc != docell4)) + { + for(i=0;i<endsamples;i++) + { + k = k*1664525+1013904223; + (cell[16].cellfunc)((void *)&cell[16],k&((WAVPREC>>1)-1)); //Snare + (cell[7].cellfunc)((void *)&cell[7],k&(WAVPREC-1)); //Hihat + (cell[17].cellfunc)((void *)&cell[17],k&((WAVPREC>>3)-1)); //Cymbal + (cell[8].cellfunc)((void *)&cell[8],0.0); //TomTom + nrptr[7][i] += cell[7].val + cell[16].val; + nrptr[8][i] += cell[8].val + cell[17].val; + } + } + } + for(j=9-1;j>=0;j--) + { + if ((adlibreg[0xbd]&0x20) && (j >= 6) && (j < 9)) continue; + + cptr = &cell[j]; k = j; + if (adlibreg[0xc0+k]&1) + { + if ((cptr[9].cellfunc == docell4) && (cptr->cellfunc == docell4)) continue; + for(i=0;i<endsamples;i++) + { + (cptr->cellfunc)((void *)cptr,cptr->val*cptr->mfb); + (cptr->cellfunc)((void *)&cptr[9],0); + nrptr[j][i] += cptr[9].val + cptr->val; + } + } + else + { + if (cptr[9].cellfunc == docell4) continue; + for(i=0;i<endsamples;i++) + { + (cptr->cellfunc)((void *)cptr,cptr->val*cptr->mfb); + (cptr[9].cellfunc)((void *)&cptr[9],cptr->val*WAVPREC*MODFACTOR); + nrptr[j][i] += cptr[9].val; + } + } + } + + if (numspeakers == 1) + { + if (bytespersample == 1) + { + for(i=endsamples-1;i>=0;i--) + clipit8(nrptr[0][i]*nlvol[0],sndptr+1); + } + else + { + for(i=endsamples-1;i>=0;i--) + clipit16(nrptr[0][i]*nlvol[0],sndptr2+i); + } + } + else + { + memset((void *)snd,0,endsamples*sizeof(float)*2); + for(j=0;j<rptrs;j++) + { + for(i=0;i<endsamples;i++) + { + snd[(i<<1) ] += rbuf[j][(nlplc[j]+i)&(FIFOSIZ*2-1)]*nlvol[j]; + snd[(i<<1)+1] += rbuf[j][(nrplc[j]+i)&(FIFOSIZ*2-1)]*nrvol[j]; + } + nlplc[j] += endsamples; + nrplc[j] += endsamples; + } + + if (bytespersample == 1) + { + for(i=(endsamples<<1)-1;i>=0;i--) + clipit8(snd[i],sndptr+i); + } + else + { + for(i=(endsamples<<1)-1;i>=0;i--) + clipit16(snd[i],sndptr2+i); + } + } + + sndptr = sndptr+(numspeakers*endsamples); + sndptr2 = sndptr2+(numspeakers*endsamples); + rend = ((rend+endsamples)&(FIFOSIZ*2-1)); } } diff --git a/src/adplug/core/adlibemu.h b/src/adplug/core/adlibemu.h index 576e57f..579a1e6 100644 --- a/src/adplug/core/adlibemu.h +++ b/src/adplug/core/adlibemu.h @@ -2,17 +2,17 @@ * ADLIBEMU.H * Copyright (C) 1998-2001 Ken Silverman * Ken Silverman's official web site: "http://www.advsys.net/ken" - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA diff --git a/src/adplug/core/adplug.cc b/src/adplug/core/adplug.cc index b2eedc4..10a149b 100644 --- a/src/adplug/core/adplug.cc +++ b/src/adplug/core/adplug.cc @@ -21,7 +21,7 @@ #include <cstring> #include <string> -#include <binfile.h> +#include "binfile.h" #include "adplug.h" #include "debug.h" @@ -69,198 +69,122 @@ #include "adl.h" #include "jbm.h" -/***** Defines *****/ - -#define ADPLUG_VERSION "1.6" - /***** CAdPlug *****/ // List of all players that come with the standard AdPlug distribution -/*const CPlayerDesc - CAdPlug::allplayers[] = { - CPlayerDesc (ChscPlayer::factory, "HSC-Tracker", ".hsc\0"), - CPlayerDesc (CsngPlayer::factory, "SNGPlay", ".sng\0"), - CPlayerDesc (CimfPlayer::factory, "Apogee IMF", ".imf\0.wlf\0.adlib\0"), - CPlayerDesc (Ca2mLoader::factory, "Adlib Tracker 2", ".a2m\0"), - CPlayerDesc (CadtrackLoader::factory, "Adlib Tracker", ".sng\0"), - CPlayerDesc (CamdLoader::factory, "AMUSIC", ".amd\0"), - CPlayerDesc (CbamPlayer::factory, "Bob's Adlib Music", ".bam\0"), - CPlayerDesc (CcmfPlayer::factory, "Creative Music File", ".cmf\0"), - CPlayerDesc (Cd00Player::factory, "Packed EdLib", ".d00\0"), - CPlayerDesc (CdfmLoader::factory, "Digital-FM", ".dfm\0"), - CPlayerDesc (ChspLoader::factory, "HSC Packed", ".hsp\0"), - CPlayerDesc (CksmPlayer::factory, "Ken Silverman Music", ".ksm\0"), - CPlayerDesc (CmadLoader::factory, "Mlat Adlib Tracker", ".mad\0"), - CPlayerDesc (CmidPlayer::factory, "MIDI", ".sci\0.laa\0"), - CPlayerDesc (CmkjPlayer::factory, "MKJamz", ".mkj\0"), - CPlayerDesc (CcffLoader::factory, "Boomtracker", ".cff\0"), - CPlayerDesc (CdmoLoader::factory, "TwinTeam", ".dmo\0"), - CPlayerDesc (Cs3mPlayer::factory, "Scream Tracker 3", ".s3m\0"), - CPlayerDesc (CdtmLoader::factory, "DeFy Adlib Tracker", ".dtm\0"), - CPlayerDesc (CfmcLoader::factory, "Faust Music Creator", ".sng\0"), - CPlayerDesc (CmtkLoader::factory, "MPU-401 Trakker", ".mtk\0"), - CPlayerDesc (CradLoader::factory, "Reality Adlib Tracker", ".rad\0"), - CPlayerDesc (CrawPlayer::factory, "RdosPlay RAW", ".raw\0"), - CPlayerDesc (Csa2Loader::factory, "Surprise! Adlib Tracker", - ".sat\0.sa2\0"), - CPlayerDesc (CxadbmfPlayer::factory, "BMF Adlib Tracker", ".xad\0"), - CPlayerDesc (CxadflashPlayer::factory, "Flash", ".xad\0"), - CPlayerDesc (CxadhybridPlayer::factory, "Hybrid", ".xad\0"), - CPlayerDesc (CxadhypPlayer::factory, "Hypnosis", ".xad\0"), - CPlayerDesc (CxadpsiPlayer::factory, "PSI", ".xad\0"), - CPlayerDesc (CxadratPlayer::factory, "rat", ".xad\0"), - CPlayerDesc (CldsPlayer::factory, "LOUDNESS Sound System", ".lds\0"), - CPlayerDesc (Cu6mPlayer::factory, "Ultima 6 Music", ".m\0"), - CPlayerDesc (CrolPlayer::factory, "Adlib Visual Composer", ".rol\0"), - CPlayerDesc (CxsmPlayer::factory, "eXtra Simple Music", ".xsm\0"), - CPlayerDesc (CdroPlayer::factory, "DOSBox Raw OPL v0.1", ".dro\0"), - CPlayerDesc (Cdro2Player::factory, "DOSBox Raw OPL v2.0", ".dro\0"), - CPlayerDesc (CmscPlayer::factory, "Adlib MSC Player", ".msc\0"), - CPlayerDesc (CrixPlayer::factory, "Softstar RIX OPL Music", ".rix\0"), - CPlayerDesc (CadlPlayer::factory, "Westwood ADL", ".adl\0"), - CPlayerDesc (CjbmPlayer::factory, "Johannes Bjerregaard", ".jbm\0"), - CPlayerDesc () +const CPlayerDesc CAdPlug::allplayers[] = { + CPlayerDesc(ChscPlayer::factory, "HSC-Tracker", ".hsc\0"), + CPlayerDesc(CsngPlayer::factory, "SNGPlay", ".sng\0"), + CPlayerDesc(CimfPlayer::factory, "Apogee IMF", ".imf\0.wlf\0.adlib\0"), + CPlayerDesc(Ca2mLoader::factory, "Adlib Tracker 2", ".a2m\0"), + CPlayerDesc(CadtrackLoader::factory, "Adlib Tracker", ".sng\0"), + CPlayerDesc(CamdLoader::factory, "AMUSIC", ".amd\0"), + CPlayerDesc(CbamPlayer::factory, "Bob's Adlib Music", ".bam\0"), + CPlayerDesc(CcmfPlayer::factory, "Creative Music File", ".cmf\0"), + CPlayerDesc(Cd00Player::factory, "Packed EdLib", ".d00\0"), + CPlayerDesc(CdfmLoader::factory, "Digital-FM", ".dfm\0"), + CPlayerDesc(ChspLoader::factory, "HSC Packed", ".hsp\0"), + CPlayerDesc(CksmPlayer::factory, "Ken Silverman Music", ".ksm\0"), + CPlayerDesc(CmadLoader::factory, "Mlat Adlib Tracker", ".mad\0"), + CPlayerDesc(CmidPlayer::factory, "MIDI", ".mid\0.sci\0.laa\0"), + CPlayerDesc(CmkjPlayer::factory, "MKJamz", ".mkj\0"), + CPlayerDesc(CcffLoader::factory, "Boomtracker", ".cff\0"), + CPlayerDesc(CdmoLoader::factory, "TwinTeam", ".dmo\0"), + CPlayerDesc(Cs3mPlayer::factory, "Scream Tracker 3", ".s3m\0"), + CPlayerDesc(CdtmLoader::factory, "DeFy Adlib Tracker", ".dtm\0"), + CPlayerDesc(CfmcLoader::factory, "Faust Music Creator", ".sng\0"), + CPlayerDesc(CmtkLoader::factory, "MPU-401 Trakker", ".mtk\0"), + CPlayerDesc(CradLoader::factory, "Reality Adlib Tracker", ".rad\0"), + CPlayerDesc(CrawPlayer::factory, "RdosPlay RAW", ".raw\0"), + CPlayerDesc(Csa2Loader::factory, "Surprise! Adlib Tracker", ".sat\0.sa2\0"), + CPlayerDesc(CxadbmfPlayer::factory, "BMF Adlib Tracker", ".xad\0"), + CPlayerDesc(CxadflashPlayer::factory, "Flash", ".xad\0"), + CPlayerDesc(CxadhybridPlayer::factory, "Hybrid", ".xad\0"), + CPlayerDesc(CxadhypPlayer::factory, "Hypnosis", ".xad\0"), + CPlayerDesc(CxadpsiPlayer::factory, "PSI", ".xad\0"), + CPlayerDesc(CxadratPlayer::factory, "rat", ".xad\0"), + CPlayerDesc(CldsPlayer::factory, "LOUDNESS Sound System", ".lds\0"), + CPlayerDesc(Cu6mPlayer::factory, "Ultima 6 Music", ".m\0"), + CPlayerDesc(CrolPlayer::factory, "Adlib Visual Composer", ".rol\0"), + CPlayerDesc(CxsmPlayer::factory, "eXtra Simple Music", ".xsm\0"), + CPlayerDesc(CdroPlayer::factory, "DOSBox Raw OPL v0.1", ".dro\0"), + CPlayerDesc(Cdro2Player::factory, "DOSBox Raw OPL v2.0", ".dro\0"), + CPlayerDesc(CmscPlayer::factory, "Adlib MSC Player", ".msc\0"), + CPlayerDesc(CrixPlayer::factory, "Softstar RIX OPL Music", ".rix\0"), + CPlayerDesc(CadlPlayer::factory, "Westwood ADL", ".adl\0"), + CPlayerDesc(CjbmPlayer::factory, "JBM Adlib Music", ".jbm\0"), + CPlayerDesc() }; -*/ -const - CPlayers & -CAdPlug::init_players (const CPlayerDesc pd[]) + +const CPlayers &CAdPlug::init_players(const CPlayerDesc pd[]) { - static CPlayers initplayers; - unsigned int i; + static CPlayers initplayers; + unsigned int i; - for (i = 0; pd[i].factory; i++) - initplayers.push_back (&pd[i]); + for(i = 0; pd[i].factory; i++) + initplayers.push_back(&pd[i]); return initplayers; } -const CPlayers& CAdPlug::getPlayers() { - static const CPlayerDesc - _allplayers[] = { - CPlayerDesc (ChscPlayer::factory, "HSC-Tracker", ".hsc\0"), - CPlayerDesc (CsngPlayer::factory, "SNGPlay", ".sng\0"), - CPlayerDesc (CimfPlayer::factory, "Apogee IMF", ".imf\0.wlf\0.adlib\0"), - CPlayerDesc (Ca2mLoader::factory, "Adlib Tracker 2", ".a2m\0"), - CPlayerDesc (CadtrackLoader::factory, "Adlib Tracker", ".sng\0"), - CPlayerDesc (CamdLoader::factory, "AMUSIC", ".amd\0"), - CPlayerDesc (CbamPlayer::factory, "Bob's Adlib Music", ".bam\0"), - CPlayerDesc (CcmfPlayer::factory, "Creative Music File", ".cmf\0"), - CPlayerDesc (Cd00Player::factory, "Packed EdLib", ".d00\0"), - CPlayerDesc (CdfmLoader::factory, "Digital-FM", ".dfm\0"), - CPlayerDesc (ChspLoader::factory, "HSC Packed", ".hsp\0"), - CPlayerDesc (CksmPlayer::factory, "Ken Silverman Music", ".ksm\0"), - CPlayerDesc (CmadLoader::factory, "Mlat Adlib Tracker", ".mad\0"), - CPlayerDesc (CmidPlayer::factory, "MIDI", ".sci\0.laa\0"), - CPlayerDesc (CmkjPlayer::factory, "MKJamz", ".mkj\0"), - CPlayerDesc (CcffLoader::factory, "Boomtracker", ".cff\0"), - CPlayerDesc (CdmoLoader::factory, "TwinTeam", ".dmo\0"), - CPlayerDesc (Cs3mPlayer::factory, "Scream Tracker 3", ".s3m\0"), - CPlayerDesc (CdtmLoader::factory, "DeFy Adlib Tracker", ".dtm\0"), - CPlayerDesc (CfmcLoader::factory, "Faust Music Creator", ".sng\0"), - CPlayerDesc (CmtkLoader::factory, "MPU-401 Trakker", ".mtk\0"), - CPlayerDesc (CradLoader::factory, "Reality Adlib Tracker", ".rad\0"), - CPlayerDesc (CrawPlayer::factory, "RdosPlay RAW", ".raw\0"), - CPlayerDesc (Csa2Loader::factory, "Surprise! Adlib Tracker", - ".sat\0.sa2\0"), - CPlayerDesc (CxadbmfPlayer::factory, "BMF Adlib Tracker", ".xad\0"), - CPlayerDesc (CxadflashPlayer::factory, "Flash", ".xad\0"), - CPlayerDesc (CxadhybridPlayer::factory, "Hybrid", ".xad\0"), - CPlayerDesc (CxadhypPlayer::factory, "Hypnosis", ".xad\0"), - CPlayerDesc (CxadpsiPlayer::factory, "PSI", ".xad\0"), - CPlayerDesc (CxadratPlayer::factory, "rat", ".xad\0"), - CPlayerDesc (CldsPlayer::factory, "LOUDNESS Sound System", ".lds\0"), - CPlayerDesc (Cu6mPlayer::factory, "Ultima 6 Music", ".m\0"), - CPlayerDesc (CrolPlayer::factory, "Adlib Visual Composer", ".rol\0"), - CPlayerDesc (CxsmPlayer::factory, "eXtra Simple Music", ".xsm\0"), - CPlayerDesc (CdroPlayer::factory, "DOSBox Raw OPL v0.1", ".dro\0"), - CPlayerDesc (Cdro2Player::factory, "DOSBox Raw OPL v2.0", ".dro\0"), - CPlayerDesc (CmscPlayer::factory, "Adlib MSC Player", ".msc\0"), - CPlayerDesc (CrixPlayer::factory, "Softstar RIX OPL Music", ".rix\0"), - CPlayerDesc (CadlPlayer::factory, "Westwood ADL", ".adl\0"), - CPlayerDesc (CjbmPlayer::factory, "Johannes Bjerregaard", ".jbm\0"), - CPlayerDesc () - }; - static CPlayers players = CAdPlug::init_players(_allplayers); - return players; -} +const CPlayers CAdPlug::players = CAdPlug::init_players(CAdPlug::allplayers); +CAdPlugDatabase *CAdPlug::database = 0; -CAdPlugDatabase * - CAdPlug::database = 0; - -CPlayer * -CAdPlug::factory (VFSFile & fd, Copl * opl, const CPlayers & pl, - const CFileProvider & fp) +CPlayer *CAdPlug::factory(const std::string &fn, Copl *opl, + const CFileProvider &fp, const CPlayers &pl) { - CPlayer *p; - CPlayers::const_iterator i; - unsigned int j; + CPlayer *p; + CPlayers::const_iterator i; + unsigned int j; - // Try a direct hit by file extension - for (i = pl.begin (); i != pl.end (); i++) - { - for (j = 0; (*i)->get_extension (j); j++) - { - if (fp.extension (fd.filename (), (*i)->get_extension (j))) - { - AdPlug_LogWrite ("Trying direct hit: %s\n", (*i)->filetype.c_str ()); + AdPlug_LogWrite("*** CAdPlug::factory(\"%s\",opl,fp) ***\n", fn.c_str()); - if ((p = (*i)->factory (opl))) - { - if (p->load (fd, fp)) - { - AdPlug_LogWrite ("got it!\n"); - AdPlug_LogWrite ("--- CAdPlug::factory ---\n"); + // Try a direct hit by file extension + for(i = pl.begin(); i != pl.end(); i++) + for(j = 0; (*i)->get_extension(j); j++) + if(fp.extension(fn, (*i)->get_extension(j))) { + AdPlug_LogWrite("Trying direct hit: %s\n", (*i)->filetype.c_str()); + if((p = (*i)->factory(opl))) { + if(p->load(fn, fp)) { + AdPlug_LogWrite("got it!\n"); + AdPlug_LogWrite("--- CAdPlug::factory ---\n"); return p; - } - - delete p; - - if (fd.fseek (0, VFS_SEEK_SET) < 0) - return 0; + } else + delete p; } } - } - } -#if 0 // Try all players, one by one - for (i = pl.begin (); i != pl.end (); i++) - { - AdPlug_LogWrite ("Trying: %s\n", (*i)->filetype.c_str ()); - if ((p = (*i)->factory (opl))) - if (p->load (fd, fp)) - { - AdPlug_LogWrite ("got it!\n"); - AdPlug_LogWrite ("--- CAdPlug::factory ---\n"); + for(i = pl.begin(); i != pl.end(); i++) { + AdPlug_LogWrite("Trying: %s\n", (*i)->filetype.c_str()); + if((p = (*i)->factory(opl))) { + if(p->load(fn, fp)) { + AdPlug_LogWrite("got it!\n"); + AdPlug_LogWrite("--- CAdPlug::factory ---\n"); return p; - } - else + } else delete p; + } } -#endif // Unknown file - AdPlug_LogWrite ("End of list!\n"); - AdPlug_LogWrite ("--- CAdPlug::factory ---\n"); + AdPlug_LogWrite("End of list!\n"); + AdPlug_LogWrite("--- CAdPlug::factory ---\n"); return 0; } -void -CAdPlug::set_database (CAdPlugDatabase * db) +void CAdPlug::set_database(CAdPlugDatabase *db) { database = db; } -std::string CAdPlug::get_version () +std::string CAdPlug::get_version() { - return std::string (ADPLUG_VERSION); + return std::string(VERSION); } -void -CAdPlug::debug_output (const std::string & filename) +void CAdPlug::debug_output(const std::string &filename) { - AdPlug_LogFile (filename.c_str ()); - AdPlug_LogWrite ("CAdPlug::debug_output(\"%s\"): Redirected.\n", - filename.c_str ()); + AdPlug_LogFile(filename.c_str()); + AdPlug_LogWrite("CAdPlug::debug_output(\"%s\"): Redirected.\n",filename.c_str()); } diff --git a/src/adplug/core/adplug.h b/src/adplug/core/adplug.h index 1283ea7..6b247bf 100644 --- a/src/adplug/core/adplug.h +++ b/src/adplug/core/adplug.h @@ -1,17 +1,17 @@ /* * AdPlug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -35,11 +35,11 @@ class CAdPlug friend CPlayer::CPlayer(Copl *newopl); public: - static const CPlayers& getPlayers(); + static const CPlayers players; - static CPlayer *factory(VFSFile &fd, Copl *opl, - const CPlayers &pl = getPlayers(), - const CFileProvider &fp = CProvider_Filesystem()); + static CPlayer *factory(const std::string &fn, Copl *opl, + const CFileProvider &fp, + const CPlayers &pl = players); static void set_database(CAdPlugDatabase *db); static std::string get_version(); @@ -47,6 +47,7 @@ public: private: static CAdPlugDatabase *database; + static const CPlayerDesc allplayers[]; static const CPlayers &init_players(const CPlayerDesc pd[]); }; diff --git a/src/adplug/core/adtrack.cc b/src/adplug/core/adtrack.cc index b410180..f8fc466 100644 --- a/src/adplug/core/adtrack.cc +++ b/src/adplug/core/adtrack.cc @@ -37,176 +37,114 @@ /*** Public methods ***/ -CPlayer * -CadtrackLoader::factory (Copl * newopl) +CPlayer *CadtrackLoader::factory(Copl *newopl) { - return new CadtrackLoader (newopl); + return new CadtrackLoader(newopl); } -bool -CadtrackLoader::load (VFSFile & fd, const CFileProvider & fp) +bool CadtrackLoader::load(const std::string &filename, const CFileProvider &fp) { - binistream *f = fp.open (fd); - if (!f) - return false; + binistream *f = fp.open(filename); if(!f) return false; binistream *instf; char note[2]; unsigned short rwp; unsigned char chp, octave, pnote = 0; - int i, j; + int i,j; AdTrackInst myinst; - std::string filename (fd.filename ()); // file validation - if (!fp.extension (filename, ".sng") || fp.filesize (f) != 36000) - { - fp.close (f); - return false; - } + if(!fp.extension(filename, ".sng") || fp.filesize(f) != 36000) + { fp.close(f); return false; } // check for instruments file - std::string instfilename (filename, 0, filename.find_last_of ('.')); + std::string instfilename(filename, 0, filename.find_last_of('.')); instfilename += ".ins"; - AdPlug_LogWrite ("CadtrackLoader::load(,\"%s\"): Checking for \"%s\"...\n", - filename.c_str (), instfilename.c_str ()); - - VFSFile instfd (instfilename.c_str (), "rb"); - instf = fp.open (instfd); - if (!instf || fp.filesize (instf) != 468) - { - fp.close (f); - return false; - } + AdPlug_LogWrite("CadtrackLoader::load(,\"%s\"): Checking for \"%s\"...\n", + filename.c_str(), instfilename.c_str()); + instf = fp.open(instfilename); + if(!instf || fp.filesize(instf) != 468) { fp.close(f); return false; } // give CmodPlayer a hint on what we're up to - realloc_patterns (1, 1000, 9); - realloc_instruments (9); - realloc_order (1); - init_trackord (); - flags = NoKeyOn; - (*order) = 0; - length = 1; - restartpos = 0; - bpm = 120; - initspeed = 3; + realloc_patterns(1,1000,9); realloc_instruments(9); realloc_order(1); + init_trackord(); flags = NoKeyOn; + (*order) = 0; length = 1; restartpos = 0; bpm = 120; initspeed = 3; // load instruments from instruments file - for (i = 0; i < 9; i++) - { - for (j = 0; j < 2; j++) - { - myinst.op[j].appampmod = instf->readInt (2); - myinst.op[j].appvib = instf->readInt (2); - myinst.op[j].maintsuslvl = instf->readInt (2); - myinst.op[j].keybscale = instf->readInt (2); - myinst.op[j].octave = instf->readInt (2); - myinst.op[j].freqrisevollvldn = instf->readInt (2); - myinst.op[j].softness = instf->readInt (2); - myinst.op[j].attack = instf->readInt (2); - myinst.op[j].decay = instf->readInt (2); - myinst.op[j].release = instf->readInt (2); - myinst.op[j].sustain = instf->readInt (2); - myinst.op[j].feedback = instf->readInt (2); - myinst.op[j].waveform = instf->readInt (2); + for(i=0;i<9;i++) { + for(j=0;j<2;j++) { + myinst.op[j].appampmod = instf->readInt(2); + myinst.op[j].appvib = instf->readInt(2); + myinst.op[j].maintsuslvl = instf->readInt(2); + myinst.op[j].keybscale = instf->readInt(2); + myinst.op[j].octave = instf->readInt(2); + myinst.op[j].freqrisevollvldn = instf->readInt(2); + myinst.op[j].softness = instf->readInt(2); + myinst.op[j].attack = instf->readInt(2); + myinst.op[j].decay = instf->readInt(2); + myinst.op[j].release = instf->readInt(2); + myinst.op[j].sustain = instf->readInt(2); + myinst.op[j].feedback = instf->readInt(2); + myinst.op[j].waveform = instf->readInt(2); } - convert_instrument (i, &myinst); + convert_instrument(i, &myinst); } - fp.close (instf); + fp.close(instf); // load file - for (rwp = 0; rwp < 1000; rwp++) - for (chp = 0; chp < 9; chp++) - { + for(rwp=0;rwp<1000;rwp++) + for(chp=0;chp<9;chp++) { // read next record - f->readString (note, 2); - octave = f->readInt (1); - f->ignore (); - switch (*note) - { - case 'C': - if (note[1] == '#') - pnote = 2; - else - pnote = 1; - break; - case 'D': - if (note[1] == '#') - pnote = 4; - else - pnote = 3; - break; - case 'E': - pnote = 5; - break; - case 'F': - if (note[1] == '#') - pnote = 7; - else - pnote = 6; - break; - case 'G': - if (note[1] == '#') - pnote = 9; - else - pnote = 8; - break; - case 'A': - if (note[1] == '#') - pnote = 11; - else - pnote = 10; - break; - case 'B': - pnote = 12; - break; + f->readString(note, 2); octave = f->readInt(1); f->ignore(); + switch(*note) { + case 'C': if(note[1] == '#') pnote = 2; else pnote = 1; break; + case 'D': if(note[1] == '#') pnote = 4; else pnote = 3; break; + case 'E': pnote = 5; break; + case 'F': if(note[1] == '#') pnote = 7; else pnote = 6; break; + case 'G': if(note[1] == '#') pnote = 9; else pnote = 8; break; + case 'A': if(note[1] == '#') pnote = 11; else pnote = 10; break; + case 'B': pnote = 12; break; case '\0': - if (note[1] == '\0') + if(note[1] == '\0') tracks[chp][rwp].note = 127; - else - { - fp.close (f); + else { + fp.close(f); return false; } break; - default: - fp.close (f); - return false; + default: fp.close(f); return false; } - if ((*note) != '\0') - { + if((*note) != '\0') { tracks[chp][rwp].note = pnote + (octave * 12); tracks[chp][rwp].inst = chp + 1; } } - fp.close (f); - rewind (0); + fp.close(f); + rewind(0); return true; } -float -CadtrackLoader::getrefresh () +float CadtrackLoader::getrefresh() { return 18.2f; } /*** Private methods ***/ -void -CadtrackLoader::convert_instrument (unsigned int n, AdTrackInst * i) +void CadtrackLoader::convert_instrument(unsigned int n, AdTrackInst *i) { // Carrier "Amp Mod / Vib / Env Type / KSR / Multiple" register inst[n].data[2] = i->op[Carrier].appampmod ? 1 << 7 : 0; inst[n].data[2] += i->op[Carrier].appvib ? 1 << 6 : 0; inst[n].data[2] += i->op[Carrier].maintsuslvl ? 1 << 5 : 0; inst[n].data[2] += i->op[Carrier].keybscale ? 1 << 4 : 0; - inst[n].data[2] += (i->op[Carrier].octave + 1) & 0xffff; // Bug in original tracker + inst[n].data[2] += (i->op[Carrier].octave + 1) & 0xffff; // Bug in original tracker // Modulator... inst[n].data[1] = i->op[Modulator].appampmod ? 1 << 7 : 0; inst[n].data[1] += i->op[Modulator].appvib ? 1 << 6 : 0; inst[n].data[1] += i->op[Modulator].maintsuslvl ? 1 << 5 : 0; inst[n].data[1] += i->op[Modulator].keybscale ? 1 << 4 : 0; - inst[n].data[1] += (i->op[Modulator].octave + 1) & 0xffff; // Bug in original tracker + inst[n].data[1] += (i->op[Modulator].octave + 1) & 0xffff; // Bug in original tracker // Carrier "Key Scaling / Level" register inst[n].data[10] = (i->op[Carrier].freqrisevollvldn & 3) << 6; diff --git a/src/adplug/core/adtrack.h b/src/adplug/core/adtrack.h index c4df633..5aae820 100644 --- a/src/adplug/core/adtrack.h +++ b/src/adplug/core/adtrack.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2003 Simon Peter <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -26,28 +26,28 @@ class CadtrackLoader: public CmodPlayer public: static CPlayer *factory(Copl *newopl); - CadtrackLoader(Copl *newopl) - : CmodPlayer(newopl) - { }; + CadtrackLoader(Copl *newopl) + : CmodPlayer(newopl) + { }; - bool load(VFSFile &fd, const CFileProvider &fp); - float getrefresh(); + bool load(const std::string &filename, const CFileProvider &fp); + float getrefresh(); - std::string gettype() - { return std::string("Adlib Tracker 1.0"); }; - unsigned int getinstruments() - { return 9; }; + std::string gettype() + { return std::string("Adlib Tracker 1.0"); }; + unsigned int getinstruments() + { return 9; }; private: enum Operators {Carrier = 1, Modulator = 0}; - typedef struct { - struct { - unsigned short appampmod, appvib, maintsuslvl, keybscale, octave, - freqrisevollvldn, softness, attack, decay, release, sustain, - feedback, waveform; - } op[2]; - } AdTrackInst; + typedef struct { + struct { + unsigned short appampmod, appvib, maintsuslvl, keybscale, octave, + freqrisevollvldn, softness, attack, decay, release, sustain, + feedback, waveform; + } op[2]; + } AdTrackInst; - void convert_instrument(unsigned int n, AdTrackInst *i); + void convert_instrument(unsigned int n, AdTrackInst *i); }; diff --git a/src/adplug/core/amd.cc b/src/adplug/core/amd.cc index 215a485..3b3b33b 100644 --- a/src/adplug/core/amd.cc +++ b/src/adplug/core/amd.cc @@ -24,26 +24,21 @@ #include "amd.h" #include "debug.h" -CPlayer * -CamdLoader::factory (Copl * newopl) +CPlayer *CamdLoader::factory(Copl *newopl) { - return new CamdLoader (newopl); + return new CamdLoader(newopl); } -bool -CamdLoader::load (VFSFile & fd, const CFileProvider & fp) +bool CamdLoader::load(const std::string &filename, const CFileProvider &fp) { - binistream *f = fp.open (fd); - if (!f) - return false; - struct - { + binistream *f = fp.open(filename); if(!f) return false; + struct { char id[9]; unsigned char version; } header; int i, j, k, t, numtrax, maxi = 0; unsigned char buf, buf2, buf3; - const unsigned char convfx[10] = { 0, 1, 2, 9, 17, 11, 13, 18, 3, 14 }; + const unsigned char convfx[10] = {0,1,2,9,17,11,13,18,3,14}; const unsigned char convvol[64] = { 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 9, 0xa, 0xa, 0xb, 0xc, 0xc, 0xd, 0xe, 0xe, 0xf, 0x10, 0x10, 0x11, 0x12, 0x13, 0x14, 0x14, @@ -53,56 +48,40 @@ CamdLoader::load (VFSFile & fd, const CFileProvider & fp) }; // file validation section - if (fp.filesize (f) < 1072) - { - fp.close (f); - return false; - } - f->seek (1062); - f->readString (header.id, 9); - header.version = f->readInt (1); - if (strncmp (header.id, "<o\xefQU\xeeRoR", 9) && - strncmp (header.id, "MaDoKaN96", 9)) - { - fp.close (f); - return false; - } + if(fp.filesize(f) < 1072) { fp.close(f); return false; } + f->seek(1062); f->readString(header.id, 9); + header.version = f->readInt(1); + if(strncmp(header.id, "<o\xefQU\xeeRoR", 9) && + strncmp(header.id, "MaDoKaN96", 9)) { fp.close(f); return false; } // load section - memset (inst, 0, 26 * sizeof (inst[0])); // memset (inst, 0, sizeof (inst)); - f->seek (0); - f->readString (songname, sizeof (songname)); - f->readString (author, sizeof (author)); - for (i = 0; i < 26; i++) - { - f->readString (instname[i], 23); - for (j = 0; j < 11; j++) - inst[i].data[j] = f->readInt (1); + memset(inst, 0, sizeof(*inst)); + f->seek(0); + f->readString(songname, sizeof(songname)); + f->readString(author, sizeof(author)); + for(i = 0; i < 26; i++) { + f->readString(instname[i], 23); + for(j = 0; j < 11; j++) inst[i].data[j] = f->readInt(1); } - length = f->readInt (1); - nop = f->readInt (1) + 1; - for (i = 0; i < 128; i++) - order[i] = f->readInt (1); - f->seek (10, binio::Add); - if (header.version == 0x10) - { // unpacked module + length = f->readInt(1); nop = f->readInt(1) + 1; + for(i=0;i<128;i++) order[i] = f->readInt(1); + f->seek(10, binio::Add); + if(header.version == 0x10) { // unpacked module maxi = nop * 9; - for (i = 0; i < 64 * 9; i++) - trackord[i / 9][i % 9] = i + 1; + for(i=0;i<64*9;i++) + trackord[i/9][i%9] = i+1; t = 0; - while (!f->ateof ()) - { - for (j = 0; j < 64; j++) - for (i = t; i < t + 9; i++) - { - buf = f->readInt (1); - tracks[i][j].param2 = (buf & 127) % 10; - tracks[i][j].param1 = (buf & 127) / 10; - buf = f->readInt (1); + while(!f->ateof()) { + for(j=0;j<64;j++) + for(i=t;i<t+9;i++) { + buf = f->readInt(1); + tracks[i][j].param2 = (buf&127) % 10; + tracks[i][j].param1 = (buf&127) / 10; + buf = f->readInt(1); tracks[i][j].inst = buf >> 4; tracks[i][j].command = buf & 0x0f; - buf = f->readInt (1); - if (buf >> 4) // fix bug in AMD save routine + buf = f->readInt(1); + if(buf >> 4) // fix bug in AMD save routine tracks[i][j].note = ((buf & 14) >> 1) * 12 + (buf >> 4); else tracks[i][j].note = 0; @@ -110,27 +89,20 @@ CamdLoader::load (VFSFile & fd, const CFileProvider & fp) } t += 9; } - } - else - { // packed module - for (i = 0; i < nop; i++) - for (j = 0; j < 9; j++) - trackord[i][j] = f->readInt (2) + 1; - numtrax = f->readInt (2); - for (k = 0; k < numtrax; k++) - { - i = f->readInt (2); - if (i > 575) - i = 575; // fix corrupted modules + } else { // packed module + for(i=0;i<nop;i++) + for(j=0;j<9;j++) + trackord[i][j] = f->readInt(2) + 1; + numtrax = f->readInt(2); + for(k=0;k<numtrax;k++) { + i = f->readInt(2); + if(i > 575) i = 575; // fix corrupted modules maxi = (i + 1 > maxi ? i + 1 : maxi); j = 0; - do - { - buf = f->readInt (1); - if (buf & 128) - { - for (t = j; t < j + (buf & 127) && t < 64; t++) - { + do { + buf = f->readInt(1); + if(buf & 128) { + for(t = j; t < j + (buf & 127) && t < 64; t++) { tracks[i][t].command = 0; tracks[i][t].inst = 0; tracks[i][t].note = 0; @@ -142,27 +114,24 @@ CamdLoader::load (VFSFile & fd, const CFileProvider & fp) } tracks[i][j].param2 = buf % 10; tracks[i][j].param1 = buf / 10; - buf = f->readInt (1); + buf = f->readInt(1); tracks[i][j].inst = buf >> 4; tracks[i][j].command = buf & 0x0f; - buf = f->readInt (1); - if (buf >> 4) // fix bug in AMD save routine + buf = f->readInt(1); + if(buf >> 4) // fix bug in AMD save routine tracks[i][j].note = ((buf & 14) >> 1) * 12 + (buf >> 4); else tracks[i][j].note = 0; tracks[i][j].inst += (buf & 1) << 4; j++; - } while (j < 64); + } while(j<64); } } - fp.close (f); + fp.close(f); // convert to protracker replay data - bpm = 50; - restartpos = 0; - flags = Decimal; - for (i = 0; i < 26; i++) - { // convert instruments + bpm = 50; restartpos = 0; flags = Decimal; + for(i=0;i<26;i++) { // convert instruments buf = inst[i].data[0]; buf2 = inst[i].data[1]; inst[i].data[0] = inst[i].data[10]; @@ -180,51 +149,44 @@ CamdLoader::load (VFSFile & fd, const CFileProvider & fp) inst[i].data[8] = inst[i].data[9]; inst[i].data[9] = buf2; inst[i].data[10] = buf3; - for (j = 0; j < 23; j++) // convert names - if (instname[i][j] == '\xff') + for(j=0;j<23;j++) // convert names + if(instname[i][j] == '\xff') instname[i][j] = '\x20'; } - for (i = 0; i < maxi; i++) // convert patterns - for (j = 0; j < 64; j++) - { + for(i=0;i<maxi;i++) // convert patterns + for(j=0;j<64;j++) { tracks[i][j].command = convfx[tracks[i][j].command]; // extended command - if (tracks[i][j].command == 14) - { - if (tracks[i][j].param1 == 2) - { + if(tracks[i][j].command == 14) { + if(tracks[i][j].param1 == 2) { tracks[i][j].command = 10; tracks[i][j].param1 = tracks[i][j].param2; tracks[i][j].param2 = 0; } - if (tracks[i][j].param1 == 3) - { + if(tracks[i][j].param1 == 3) { tracks[i][j].command = 10; tracks[i][j].param1 = 0; } } // fix volume - if (tracks[i][j].command == 17) - { + if(tracks[i][j].command == 17) { int vol = convvol[tracks[i][j].param1 * 10 + tracks[i][j].param2]; - if (vol > 63) - vol = 63; + if(vol > 63) vol = 63; tracks[i][j].param1 = vol / 10; tracks[i][j].param2 = vol % 10; } } - rewind (0); + rewind(0); return true; } -float -CamdLoader::getrefresh () +float CamdLoader::getrefresh() { - if (tempo) + if(tempo) return (float) (tempo); else return 18.2f; diff --git a/src/adplug/core/amd.h b/src/adplug/core/amd.h index ba93d7b..b4b053a 100644 --- a/src/adplug/core/amd.h +++ b/src/adplug/core/amd.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -26,24 +26,24 @@ class CamdLoader: public CmodPlayer public: static CPlayer *factory(Copl *newopl); - CamdLoader(Copl *newopl) - : CmodPlayer(newopl) - { }; + CamdLoader(Copl *newopl) + : CmodPlayer(newopl) + { }; - bool load(VFSFile &fd, const CFileProvider &fp); - float getrefresh(); + bool load(const std::string &filename, const CFileProvider &fp); + float getrefresh(); - std::string gettype() - { return std::string("AMUSIC Adlib Tracker"); }; - std::string gettitle() - { return std::string(songname,0,24); }; - std::string getauthor() - { return std::string(author,0,24); }; - unsigned int getinstruments() - { return 26; }; - std::string getinstrument(unsigned int n) - { return std::string(instname[n],0,23); }; + std::string gettype() + { return std::string("AMUSIC Adlib Tracker"); }; + std::string gettitle() + { return std::string(songname,0,24); }; + std::string getauthor() + { return std::string(author,0,24); }; + unsigned int getinstruments() + { return 26; }; + std::string getinstrument(unsigned int n) + { return std::string(instname[n],0,23); }; private: - char songname[24],author[24],instname[26][23]; + char songname[24],author[24],instname[26][23]; }; diff --git a/src/adplug/core/bam.cc b/src/adplug/core/bam.cc index d542942..46a879e 100644 --- a/src/adplug/core/bam.cc +++ b/src/adplug/core/bam.cc @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -28,16 +28,16 @@ * Using just one loop counter for each label, my player can't * handle files that loop twice to the same label (if that's at * all possible with BAM). Imagine the following situation: - * + * * ... [*] ---- [<- *] ---- [<- *] ... * ^ ^ ^ ^ ^ ^ ^ * | | | | | | | * +---|----+-----|-----+-----|----+--- normal song data * +----------|-----------|-------- label 1 * +-----------+-------- loop points to label 1 - * - * both loop points loop to the same label. Storing the loop - * count with the label would cause chaos with the counter, + * + * both loop points loop to the same label. Storing the loop + * count with the label would cause chaos with the counter, * when the player executes the inner jump. * ------------------ * Not to worry. my reference implementation of BAM does not @@ -50,195 +50,154 @@ #include <string.h> #include "bam.h" -const unsigned short - CbamPlayer::freq[] = { 172, 182, 193, 205, 217, 230, 243, 258, 274, - 290, 307, 326, 345, 365, 387, 410, 435, 460, 489, 517, 547, 580, 614, 651, - 1369, 1389, 1411, - 1434, 1459, 1484, 1513, 1541, 1571, 1604, 1638, 1675, 2393, 2413, 2435, - 2458, 2483, 2508, - 2537, 2565, 2595, 2628, 2662, 2699, 3417, 3437, 3459, 3482, 3507, 3532, - 3561, 3589, 3619, - 3652, 3686, 3723, 4441, 4461, 4483, 4506, 4531, 4556, 4585, 4613, 4643, - 4676, 4710, 4747, - 5465, 5485, 5507, 5530, 5555, 5580, 5609, 5637, 5667, 5700, 5734, 5771, - 6489, 6509, 6531, - 6554, 6579, 6604, 6633, 6661, 6691, 6724, 6758, 6795, 7513, 7533, 7555, - 7578, 7603, 7628, - 7657, 7685, 7715, 7748, 7782, 7819, 7858, 7898, 7942, 7988, 8037, 8089, - 8143, 8191, 8191, - 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191, 8191 -}; +const unsigned short CbamPlayer::freq[] = {172,182,193,205,217,230,243,258,274, +290,307,326,345,365,387,410,435,460,489,517,547,580,614,651,1369,1389,1411, +1434,1459,1484,1513,1541,1571,1604,1638,1675,2393,2413,2435,2458,2483,2508, +2537,2565,2595,2628,2662,2699,3417,3437,3459,3482,3507,3532,3561,3589,3619, +3652,3686,3723,4441,4461,4483,4506,4531,4556,4585,4613,4643,4676,4710,4747, +5465,5485,5507,5530,5555,5580,5609,5637,5667,5700,5734,5771,6489,6509,6531, +6554,6579,6604,6633,6661,6691,6724,6758,6795,7513,7533,7555,7578,7603,7628, +7657,7685,7715,7748,7782,7819,7858,7898,7942,7988,8037,8089,8143,8191,8191, +8191,8191,8191,8191,8191,8191,8191,8191,8191,8191}; -CPlayer * -CbamPlayer::factory (Copl * newopl) +CPlayer *CbamPlayer::factory(Copl *newopl) { - return new CbamPlayer (newopl); + return new CbamPlayer(newopl); } -bool -CbamPlayer::load (VFSFile & fd, const CFileProvider & fp) +bool CbamPlayer::load(const std::string &filename, const CFileProvider &fp) { - binistream *f = fp.open (fd); - if (!f) - return false; - char id[4]; - unsigned int i; + binistream *f = fp.open(filename); if(!f) return false; + char id[4]; + unsigned int i; - size = fp.filesize (f) - 4; // filesize minus header - f->readString (id, 4); - if (strncmp (id, "CBMF", 4)) - { - fp.close (f); - return false; - } + size = fp.filesize(f) - 4; // filesize minus header + f->readString(id, 4); + if(strncmp(id,"CBMF",4)) { fp.close(f); return false; } - song = new unsigned char[size]; - for (i = 0; i < size; i++) - song[i] = f->readInt (1); + song = new unsigned char [size]; + for(i = 0; i < size; i++) song[i] = f->readInt(1); - fp.close (f); - rewind (0); - return true; + fp.close(f); + rewind(0); + return true; } -bool -CbamPlayer::update () +bool CbamPlayer::update() { - unsigned char cmd, c; + unsigned char cmd,c; - if (del) - { - del--; - return !songend; - } + if(del) { + del--; + return !songend; + } - if (pos >= size) - { // EOF detection - pos = 0; - songend = true; - } + if(pos >= size) { // EOF detection + pos = 0; + songend = true; + } - while (song[pos] < 128) - { - cmd = song[pos] & 240; - c = song[pos] & 15; - switch (cmd) - { - case 0: // stop song - pos = 0; - songend = true; - break; - case 16: // start note - if (c < 9) - { - opl->write (0xa0 + c, freq[song[++pos]] & 255); - opl->write (0xb0 + c, (freq[song[pos]] >> 8) + 32); - } - else - pos++; - pos++; - break; - case 32: // stop note - if (c < 9) - opl->write (0xb0 + c, 0); - pos++; - break; - case 48: // define instrument - if (c < 9) - { - opl->write (0x20 + op_table[c], song[pos + 1]); - opl->write (0x23 + op_table[c], song[pos + 2]); - opl->write (0x40 + op_table[c], song[pos + 3]); - opl->write (0x43 + op_table[c], song[pos + 4]); - opl->write (0x60 + op_table[c], song[pos + 5]); - opl->write (0x63 + op_table[c], song[pos + 6]); - opl->write (0x80 + op_table[c], song[pos + 7]); - opl->write (0x83 + op_table[c], song[pos + 8]); - opl->write (0xe0 + op_table[c], song[pos + 9]); - opl->write (0xe3 + op_table[c], song[pos + 10]); - opl->write (0xc0 + c, song[pos + 11]); - } - pos += 12; - break; - case 80: // set label - label[c].target = ++pos; - label[c].defined = true; - break; - case 96: // jump - if (label[c].defined) - switch (song[pos + 1]) - { - case 254: // infinite loop - if (label[c].defined) - { - pos = label[c].target; - songend = true; - break; - } - // fall through... - case 255: // chorus - if (!chorus && label[c].defined) - { - chorus = true; - gosub = pos + 2; - pos = label[c].target; - break; - } - // fall through... - case 0: // end of loop - pos += 2; - break; - default: // finite loop - if (!label[c].count) - { // loop elapsed - label[c].count = 255; - pos += 2; - break; - } - if (label[c].count < 255) // loop defined - label[c].count--; - else // loop undefined - label[c].count = song[pos + 1] - 1; - pos = label[c].target; - break; + while(song[pos] < 128) { + cmd = song[pos] & 240; + c = song[pos] & 15; + switch(cmd) { + case 0: // stop song + pos = 0; + songend = true; + break; + case 16: // start note + if(c < 9) { + opl->write(0xa0 + c, freq[song[++pos]] & 255); + opl->write(0xb0 + c, (freq[song[pos]] >> 8) + 32); + } else + pos++; + pos++; + break; + case 32: // stop note + if(c < 9) + opl->write(0xb0 + c, 0); + pos++; + break; + case 48: // define instrument + if(c < 9) { + opl->write(0x20 + op_table[c],song[pos+1]); + opl->write(0x23 + op_table[c],song[pos+2]); + opl->write(0x40 + op_table[c],song[pos+3]); + opl->write(0x43 + op_table[c],song[pos+4]); + opl->write(0x60 + op_table[c],song[pos+5]); + opl->write(0x63 + op_table[c],song[pos+6]); + opl->write(0x80 + op_table[c],song[pos+7]); + opl->write(0x83 + op_table[c],song[pos+8]); + opl->write(0xe0 + op_table[c],song[pos+9]); + opl->write(0xe3 + op_table[c],song[pos+10]); + opl->write(0xc0 + c,song[pos+11]); + } + pos += 12; + break; + case 80: // set label + label[c].target = ++pos; + label[c].defined = true; + break; + case 96: // jump + if(label[c].defined) + switch(song[pos+1]) { + case 254: // infinite loop + if(label[c].defined) { + pos = label[c].target; + songend = true; + break; + } + // fall through... + case 255: // chorus + if(!chorus && label[c].defined) { + chorus = true; + gosub = pos + 2; + pos = label[c].target; + break; + } + // fall through... + case 0: // end of loop + pos += 2; + break; + default: // finite loop + if(!label[c].count) { // loop elapsed + label[c].count = 255; + pos += 2; + break; + } + if(label[c].count < 255) // loop defined + label[c].count--; + else // loop undefined + label[c].count = song[pos+1] - 1; + pos = label[c].target; + break; + } + break; + case 112: // end of chorus + if(chorus) { + pos = gosub; + chorus = false; + } else + pos++; + break; + default: // reserved command (skip) + pos++; + break; + } + } + if(song[pos] >= 128) { // wait + del = song[pos] - 127; + pos++; } - break; - case 112: // end of chorus - if (chorus) - { - pos = gosub; - chorus = false; - } - else - pos++; - break; - default: // reserved command (skip) - pos++; - break; - } - } - if (song[pos] >= 128) - { // wait - del = song[pos] - 127; - pos++; - } - return !songend; + return !songend; } -void -CbamPlayer::rewind (int subsong) +void CbamPlayer::rewind(int subsong) { - int i; + int i; - pos = 0; - songend = false; - del = 0; - gosub = 0; - chorus = false; - memset (label, 0, sizeof (label)); - label[0].defined = true; - for (i = 0; i < 16; i++) - label[i].count = 255; // 255 = undefined - opl->init (); - opl->write (1, 32); + pos = 0; songend = false; del = 0; gosub = 0; chorus = false; + memset(label, 0, sizeof(label)); label[0].defined = true; + for(i = 0; i < 16; i++) label[i].count = 255; // 255 = undefined + opl->init(); opl->write(1,32); } diff --git a/src/adplug/core/bam.h b/src/adplug/core/bam.h index cf38707..d5c2287 100644 --- a/src/adplug/core/bam.h +++ b/src/adplug/core/bam.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -26,31 +26,31 @@ class CbamPlayer: public CPlayer public: static CPlayer *factory(Copl *newopl); - CbamPlayer(Copl *newopl) - : CPlayer(newopl), song(0) - { }; - ~CbamPlayer() - { if(song) delete [] song; }; + CbamPlayer(Copl *newopl) + : CPlayer(newopl), song(0) + { }; + ~CbamPlayer() + { if(song) delete [] song; }; - bool load(VFSFile &fd, const CFileProvider &fp); - bool update(); - void rewind(int subsong); - float getrefresh() - { return 25.0f; }; + bool load(const std::string &filename, const CFileProvider &fp); + bool update(); + void rewind(int subsong); + float getrefresh() + { return 25.0f; }; - std::string gettype() - { return std::string("Bob's Adlib Music"); }; + std::string gettype() + { return std::string("Bob's Adlib Music"); }; private: - static const unsigned short freq[]; + static const unsigned short freq[]; - unsigned char *song, del; - unsigned long pos, size, gosub; - bool songend, chorus; + unsigned char *song, del; + unsigned long pos, size, gosub; + bool songend, chorus; - struct { - unsigned long target; - bool defined; - unsigned char count; - } label[16]; + struct { + unsigned long target; + bool defined; + unsigned char count; + } label[16]; }; diff --git a/src/adplug/core/binio_virtual.h b/src/adplug/core/binio_virtual.h deleted file mode 100644 index 5d7f9ad..0000000 --- a/src/adplug/core/binio_virtual.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2006 William Pitcock <nenolod -at- atheme.org> - * This code is in the public domain. - */ - -#ifndef __BINIO_VIRTUAL__ -#define __BINIO_VIRTUAL__ - -#include <binio.h> -#include <stdio.h> - -#include <libaudcore/vfs.h> - -class vfsistream : public binistream { -private: - VFSFile *fd = nullptr; - VFSFile own; - -public: - vfsistream(VFSFile *fd = nullptr) : - fd(fd) {} - - void open(const char *file) { - if ((own = VFSFile(file, "r"))) - fd = &own; - else - err |= NotFound; - } - - void open(std::string &file) { open(file.c_str()); } - - vfsistream(const char *file) { open(file); } - vfsistream(std::string &file) { open(file); } - - Byte getByte() { - Byte b = (Byte)-1; - if (fd->fread(&b, 1, 1) != 1) - err |= Eof; - return b; - } - - void seek(long pos, Offset offs = Set) { - VFSSeekType wh = (offs == Add) ? VFS_SEEK_CUR : (offs == End) ? VFS_SEEK_END : VFS_SEEK_SET; - if (fd->fseek (pos, wh)) - err |= Eof; - } - - long pos() { - return fd->ftell (); - } -}; - -class vfsostream : public binostream { -private: - VFSFile *fd = nullptr; - VFSFile own; - -public: - vfsostream(VFSFile *fd = nullptr) : - fd(fd) {} - - void open(const char *file) { - if ((own = VFSFile(file, "w"))) - fd = &own; - else - err |= Denied; - } - - void open(std::string &file) { open(file.c_str()); } - - vfsostream(const char *file) { open(file); } - vfsostream(std::string &file) { open(file); } - - void putByte(Byte b) { - if (fd->fwrite (&b, 1, 1) != 1) - err |= Fatal; - } - - void seek(long pos, Offset offs = Set) { - VFSSeekType wh = (offs == Add) ? VFS_SEEK_CUR : (offs == End) ? VFS_SEEK_END : VFS_SEEK_SET; - if (fd->fseek (pos, wh)) - err |= Fatal; - } - - long pos(void) { - return fd->ftell (); - } -}; - -#endif diff --git a/src/adplug/core/bmf.cc b/src/adplug/core/bmf.cc index ff546c2..01aeada 100644 --- a/src/adplug/core/bmf.cc +++ b/src/adplug/core/bmf.cc @@ -40,74 +40,61 @@ comment : inaccurate replaying, because constant outport; in original player it can be 380 or 382. */ -#include <string.h> - +#include <cstring> #include "bmf.h" #include "debug.h" -const unsigned char - CxadbmfPlayer::bmf_adlib_registers[117] = { - 0x20, 0x23, 0x40, 0x43, 0x60, 0x63, 0x80, 0x83, 0xA0, 0xB0, 0xC0, 0xE0, - 0xE3, - 0x21, 0x24, 0x41, 0x44, 0x61, 0x64, 0x81, 0x84, 0xA1, 0xB1, 0xC1, 0xE1, - 0xE4, - 0x22, 0x25, 0x42, 0x45, 0x62, 0x65, 0x82, 0x85, 0xA2, 0xB2, 0xC2, 0xE2, - 0xE5, - 0x28, 0x2B, 0x48, 0x4B, 0x68, 0x6B, 0x88, 0x8B, 0xA3, 0xB3, 0xC3, 0xE8, - 0xEB, - 0x29, 0x2C, 0x49, 0x4C, 0x69, 0x6C, 0x89, 0x8C, 0xA4, 0xB4, 0xC4, 0xE9, - 0xEC, - 0x2A, 0x2D, 0x4A, 0x4D, 0x6A, 0x6D, 0x8A, 0x8D, 0xA5, 0xB5, 0xC5, 0xEA, - 0xED, - 0x30, 0x33, 0x50, 0x53, 0x70, 0x73, 0x90, 0x93, 0xA6, 0xB6, 0xC6, 0xF0, - 0xF3, - 0x31, 0x34, 0x51, 0x54, 0x71, 0x74, 0x91, 0x94, 0xA7, 0xB7, 0xC7, 0xF1, - 0xF4, +const unsigned char CxadbmfPlayer::bmf_adlib_registers[117] = +{ + 0x20, 0x23, 0x40, 0x43, 0x60, 0x63, 0x80, 0x83, 0xA0, 0xB0, 0xC0, 0xE0, 0xE3, + 0x21, 0x24, 0x41, 0x44, 0x61, 0x64, 0x81, 0x84, 0xA1, 0xB1, 0xC1, 0xE1, 0xE4, + 0x22, 0x25, 0x42, 0x45, 0x62, 0x65, 0x82, 0x85, 0xA2, 0xB2, 0xC2, 0xE2, 0xE5, + 0x28, 0x2B, 0x48, 0x4B, 0x68, 0x6B, 0x88, 0x8B, 0xA3, 0xB3, 0xC3, 0xE8, 0xEB, + 0x29, 0x2C, 0x49, 0x4C, 0x69, 0x6C, 0x89, 0x8C, 0xA4, 0xB4, 0xC4, 0xE9, 0xEC, + 0x2A, 0x2D, 0x4A, 0x4D, 0x6A, 0x6D, 0x8A, 0x8D, 0xA5, 0xB5, 0xC5, 0xEA, 0xED, + 0x30, 0x33, 0x50, 0x53, 0x70, 0x73, 0x90, 0x93, 0xA6, 0xB6, 0xC6, 0xF0, 0xF3, + 0x31, 0x34, 0x51, 0x54, 0x71, 0x74, 0x91, 0x94, 0xA7, 0xB7, 0xC7, 0xF1, 0xF4, 0x32, 0x35, 0x52, 0x55, 0x72, 0x75, 0x92, 0x95, 0xA8, 0xB8, 0xC8, 0xF2, 0xF5 }; -const unsigned short - CxadbmfPlayer::bmf_notes[12] = { - 0x157, 0x16B, 0x181, 0x198, 0x1B0, 0x1CA, 0x1E5, 0x202, 0x220, 0x241, 0x263, - 0x287 +const unsigned short CxadbmfPlayer::bmf_notes[12] = +{ + 0x157, 0x16B, 0x181, 0x198, 0x1B0, 0x1CA, 0x1E5, 0x202, 0x220, 0x241, 0x263, 0x287 }; /* for 1.1 */ -const unsigned short - CxadbmfPlayer::bmf_notes_2[12] = { - 0x159, 0x16D, 0x183, 0x19A, 0x1B2, 0x1CC, 0x1E8, 0x205, 0x223, 0x244, 0x267, - 0x28B +const unsigned short CxadbmfPlayer::bmf_notes_2[12] = +{ + 0x159, 0x16D, 0x183, 0x19A, 0x1B2, 0x1CC, 0x1E8, 0x205, 0x223, 0x244, 0x267, 0x28B }; -const unsigned char - CxadbmfPlayer::bmf_default_instrument[13] = { +const unsigned char CxadbmfPlayer::bmf_default_instrument[13] = +{ 0x01, 0x01, 0x3F, 0x3F, 0x00, 0x00, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00 }; -CPlayer * -CxadbmfPlayer::factory (Copl * newopl) +CPlayer *CxadbmfPlayer::factory(Copl *newopl) { - return new CxadbmfPlayer (newopl); + return new CxadbmfPlayer(newopl); } -bool -CxadbmfPlayer::xadplayer_load () +bool CxadbmfPlayer::xadplayer_load() { unsigned short ptr = 0; int i; - if (xad.fmt != BMF) + if(xad.fmt != BMF) return false; #ifdef DEBUG - AdPlug_LogWrite ("\nbmf_load():\n\n"); + AdPlug_LogWrite("\nbmf_load():\n\n"); #endif - if (!strncmp ((char *) &tune[0], "BMF1.2", 6)) + if (!strncmp((char *)&tune[0],"BMF1.2",6)) { bmf.version = BMF1_2; bmf.timer = 70.0f; } - else if (!strncmp ((char *) &tune[0], "BMF1.1", 6)) + else if (!strncmp((char *)&tune[0],"BMF1.1",6)) { bmf.version = BMF1_1; bmf.timer = 60.0f; @@ -123,105 +110,94 @@ CxadbmfPlayer::xadplayer_load () { ptr = 6; - strncpy (bmf.title, (char *) &tune[ptr], 36); + strncpy(bmf.title,(char *)&tune[ptr],36); - while (tune[ptr]) - { - ptr++; - } - ptr++; + while (tune[ptr]) { ptr++; } + ptr++; - strncpy (bmf.author, (char *) &tune[ptr], 36); + strncpy(bmf.author,(char *)&tune[ptr],36); - while (tune[ptr]) - { - ptr++; - } - ptr++; + while (tune[ptr]) { ptr++; } + ptr++; } else { - strncpy (bmf.title, xad.title, 36); - strncpy (bmf.author, xad.author, 36); + strncpy(bmf.title,xad.title,36); + strncpy(bmf.author,xad.author,36); } // speed if (bmf.version > BMF0_9B) bmf.speed = tune[ptr++]; else - bmf.speed = ((tune[ptr++] << 8) / 3) >> 8; // strange, yeh ? + bmf.speed = ((tune[ptr++] << 8) / 3) >> 8; // strange, yeh ? // load instruments if (bmf.version > BMF0_9B) { - unsigned long iflags = - (tune[ptr] << 24) | (tune[ptr + 1] << 16) | (tune[ptr + 2] << 8) | - tune[ptr + 3]; - ptr += 4; + unsigned long iflags = (tune[ptr] << 24) | (tune[ptr+1] << 16) | (tune[ptr+2] << 8) | tune[ptr+3]; + ptr+=4; - for (i = 0; i < 32; i++) - if (iflags & (1 << (31 - i))) - { - strcpy (bmf.instruments[i].name, (char *) &tune[ptr]); - memcpy (bmf.instruments[i].data, &tune[ptr + 11], 13); + for(i=0;i<32;i++) + if (iflags & (1 << (31-i))) + { + strcpy(bmf.instruments[i].name, (char *)&tune[ptr]); + memcpy(bmf.instruments[i].data, &tune[ptr+11], 13); ptr += 24; - } + } else - { + { bmf.instruments[i].name[0] = 0; if (bmf.version == BMF1_1) - for (int j = 0; j < 13; j++) - bmf.instruments[i].data[j] = bmf_default_instrument[j]; + for(int j=0;j<13;j++) + bmf.instruments[i].data[j] = bmf_default_instrument[j]; else - for (int j = 0; j < 13; j++) - bmf.instruments[i].data[j] = 0; - } + for(int j=0;j<13;j++) + bmf.instruments[i].data[j] = 0; + } } else { ptr = 6; - for (i = 0; i < 32; i++) + for(i=0;i<32;i++) { bmf.instruments[i].name[0] = 0; - memcpy (bmf.instruments[tune[ptr]].data, &tune[ptr + 2], 13); // bug no.1 (no instrument-table-end detection) - ptr += 15; + memcpy(bmf.instruments[tune[ptr]].data, &tune[ptr+2],13); // bug no.1 (no instrument-table-end detection) + ptr+=15; } } // load streams if (bmf.version > BMF0_9B) { - unsigned long sflags = - (tune[ptr] << 24) | (tune[ptr + 1] << 16) | (tune[ptr + 2] << 8) | - tune[ptr + 3]; - ptr += 4; - - for (i = 0; i < 9; i++) - if (sflags & (1 << (31 - i))) - ptr += __bmf_convert_stream (&tune[ptr], i); + unsigned long sflags = (tune[ptr] << 24) | (tune[ptr+1] << 16) | (tune[ptr+2] << 8) | tune[ptr+3]; + ptr+=4; + + for(i=0;i<9;i++) + if (sflags & (1 << (31-i))) + ptr+=__bmf_convert_stream(&tune[ptr],i); else bmf.streams[i][0].cmd = 0xFF; } else { - for (i = 0; i < tune[5]; i++) - ptr += __bmf_convert_stream (&tune[ptr], i); + for(i=0;i<tune[5];i++) + ptr+=__bmf_convert_stream(&tune[ptr],i); - for (i = tune[5]; i < 9; i++) + for(i=tune[5];i<9;i++) bmf.streams[i][0].cmd = 0xFF; } return true; } -void -CxadbmfPlayer::xadplayer_rewind (int subsong) +void CxadbmfPlayer::xadplayer_rewind(int subsong) { - int i, j; + int i,j; - for (i = 0; i < 9; i++) + for(i=0; i<9; i++) { bmf.channel[i].stream_position = 0; bmf.channel[i].delay = 0; @@ -231,7 +207,7 @@ CxadbmfPlayer::xadplayer_rewind (int subsong) plr.speed = bmf.speed; #ifdef DEBUG - AdPlug_LogWrite ("speed: %x\n", plr.speed); + AdPlug_LogWrite("speed: %x\n",plr.speed); #endif bmf.active_streams = 9; @@ -239,216 +215,205 @@ CxadbmfPlayer::xadplayer_rewind (int subsong) // OPL initialization if (bmf.version > BMF0_9B) { - opl_write (0x01, 0x20); + opl_write(0x01, 0x20); /* 1.1 */ if (bmf.version == BMF1_1) - for (i = 0; i < 9; i++) - for (j = 0; j < 13; j++) - opl_write (bmf_adlib_registers[13 * i + j], - bmf_default_instrument[j]); + for(i=0;i<9;i++) + for(j=0;j<13;j++) + opl_write(bmf_adlib_registers[13*i+j], bmf_default_instrument[j]); /* 1.2 */ else if (bmf.version == BMF1_2) - for (i = 0x20; i < 0x100; i++) - opl_write (i, 0xFF); // very interesting, really! + for(i=0x20; i<0x100; i++) + opl_write(i,0xFF); // very interesting, really! } /* ALL */ - opl_write (0x08, 0x00); - opl_write (0xBD, 0xC0); + opl_write(0x08, 0x00); + opl_write(0xBD, 0xC0); } -void -CxadbmfPlayer::xadplayer_update () +void CxadbmfPlayer::xadplayer_update() { - for (int i = 0; i < 9; i++) + for(int i=0;i<9;i++) if (bmf.channel[i].stream_position != 0xFFFF) { - if (bmf.channel[i].delay) - bmf.channel[i].delay--; - else - { + if (bmf.channel[i].delay) + bmf.channel[i].delay--; + else + { #ifdef DEBUG - AdPlug_LogWrite ("channel %02X:\n", i); + AdPlug_LogWrite("channel %02X:\n", i); #endif - bmf_event event; + bmf_event event; - // process so-called cross-events - while (true) - { - memcpy (&event, &bmf.streams[i][bmf.channel[i].stream_position], - sizeof (bmf_event)); + // process so-called cross-events + while (true) + { + memcpy(&event, &bmf.streams[i][bmf.channel[i].stream_position], sizeof(bmf_event)); #ifdef DEBUG - AdPlug_LogWrite ("%02X %02X %02X %02X %02X %02X\n", - event.note, event.delay, event.volume, - event.instrument, event.cmd, event.cmd_data); + AdPlug_LogWrite("%02X %02X %02X %02X %02X %02X\n", + event.note,event.delay,event.volume,event.instrument, + event.cmd,event.cmd_data); #endif - if (event.cmd == 0xFF) - { - bmf.channel[i].stream_position = 0xFFFF; - bmf.active_streams--; - break; - } - else if (event.cmd == 0xFE) + if (event.cmd == 0xFF) + { + bmf.channel[i].stream_position = 0xFFFF; + bmf.active_streams--; + break; + } + else if (event.cmd == 0xFE) + { + bmf.channel[i].loop_position = bmf.channel[i].stream_position+1; + bmf.channel[i].loop_counter = event.cmd_data; + } + else if (event.cmd == 0xFD) + { + if (bmf.channel[i].loop_counter) { - bmf.channel[i].loop_position = bmf.channel[i].stream_position + 1; - bmf.channel[i].loop_counter = event.cmd_data; + bmf.channel[i].stream_position = bmf.channel[i].loop_position-1; + bmf.channel[i].loop_counter--; } - else if (event.cmd == 0xFD) - { - if (bmf.channel[i].loop_counter) - { - bmf.channel[i].stream_position = - bmf.channel[i].loop_position - 1; - bmf.channel[i].loop_counter--; - } - } - else - break; - - bmf.channel[i].stream_position++; - } // while (true) + } + else + break; - // process normal event - unsigned short pos = bmf.channel[i].stream_position; + bmf.channel[i].stream_position++; + } // while (true) - if (pos != 0xFFFF) - { - bmf.channel[i].delay = bmf.streams[i][pos].delay; + // process normal event + unsigned short pos = bmf.channel[i].stream_position; - // command ? - if (bmf.streams[i][pos].cmd) - { - unsigned char cmd = bmf.streams[i][pos].cmd; - - // 0x01: Set Modulator Volume - if (cmd == 0x01) - { - unsigned char reg = bmf_adlib_registers[13 * i + 2]; - - opl_write (reg, - (adlib[reg] | 0x3F) - bmf.streams[i][pos].cmd_data); - } - // 0x10: Set Speed - else if (cmd == 0x10) - { - plr.speed = bmf.streams[i][pos].cmd_data; - plr.speed_counter = plr.speed; - } - } // if (bmf.streams[i][pos].cmd) - - // instrument ? - if (bmf.streams[i][pos].instrument) + if (pos != 0xFFFF) + { + bmf.channel[i].delay = bmf.streams[i][pos].delay; + + // command ? + if (bmf.streams[i][pos].cmd) + { + unsigned char cmd = bmf.streams[i][pos].cmd; + + // 0x01: Set Modulator Volume + if (cmd == 0x01) + { + unsigned char reg = bmf_adlib_registers[13*i+2]; + + opl_write(reg, (adlib[reg] | 0x3F) - bmf.streams[i][pos].cmd_data); + } + // 0x10: Set Speed + else if (cmd == 0x10) + { + plr.speed = bmf.streams[i][pos].cmd_data; + plr.speed_counter = plr.speed; + } + } // if (bmf.streams[i][pos].cmd) + + // instrument ? + if (bmf.streams[i][pos].instrument) + { + unsigned char ins = bmf.streams[i][pos].instrument-1; + + if (bmf.version != BMF1_1) + opl_write(0xB0+i, adlib[0xB0+i] & 0xDF); + + for(int j=0;j<13;j++) + opl_write(bmf_adlib_registers[i*13+j], bmf.instruments[ins].data[j]); + } // if (bmf.streams[i][pos].instrument) + + // volume ? + if (bmf.streams[i][pos].volume) + { + unsigned char vol = bmf.streams[i][pos].volume-1; + unsigned char reg = bmf_adlib_registers[13*i+3]; + + opl_write(reg, (adlib[reg] | 0x3F) - vol); + } // if (bmf.streams[i][pos].volume) + + // note ? + if (bmf.streams[i][pos].note) + { + unsigned short note = bmf.streams[i][pos].note; + unsigned short freq = 0; + + // mute channel + opl_write(0xB0+i, adlib[0xB0+i] & 0xDF); + + // get frequency + if (bmf.version == BMF1_1) { - unsigned char ins = bmf.streams[i][pos].instrument - 1; - - if (bmf.version != BMF1_1) - opl_write (0xB0 + i, adlib[0xB0 + i] & 0xDF); - - for (int j = 0; j < 13; j++) - opl_write (bmf_adlib_registers[i * 13 + j], - bmf.instruments[ins].data[j]); - } // if (bmf.streams[i][pos].instrument) + if (note <= 0x60) + freq = bmf_notes_2[--note % 12]; + } + else + { + if (note != 0x7F) + freq = bmf_notes[--note % 12]; + } - // volume ? - if (bmf.streams[i][pos].volume) + // play note + if (freq) { - unsigned char vol = bmf.streams[i][pos].volume - 1; - unsigned char reg = bmf_adlib_registers[13 * i + 3]; + opl_write(0xB0+i, (freq >> 8) | ((note / 12) << 2) | 0x20); + opl_write(0xA0+i, freq & 0xFF); + } + } // if (bmf.streams[i][pos].note) - opl_write (reg, (adlib[reg] | 0x3F) - vol); - } // if (bmf.streams[i][pos].volume) + bmf.channel[i].stream_position++; + } // if (pos != 0xFFFF) - // note ? - if (bmf.streams[i][pos].note) - { - unsigned short note = bmf.streams[i][pos].note; - unsigned short freq = 0; - - // mute channel - opl_write (0xB0 + i, adlib[0xB0 + i] & 0xDF); - - // get frequency - if (bmf.version == BMF1_1) - { - if (note <= 0x60) - freq = bmf_notes_2[--note % 12]; - } - else - { - if (note != 0x7F) - freq = bmf_notes[--note % 12]; - } - - // play note - if (freq) - { - opl_write (0xB0 + i, (freq >> 8) | ((note / 12) << 2) | 0x20); - opl_write (0xA0 + i, freq & 0xFF); - } - } // if (bmf.streams[i][pos].note) - - bmf.channel[i].stream_position++; - } // if (pos != 0xFFFF) - - } // if (!bmf.channel[i].delay) - } // if (bmf.channel[i].stream_position != 0xFFFF) + } // if (!bmf.channel[i].delay) + } // if (bmf.channel[i].stream_position != 0xFFFF) // is module loop ? if (!bmf.active_streams) { - for (int j = 0; j < 9; j++) + for(int j=0;j<9;j++) bmf.channel[j].stream_position = 0; - bmf.active_streams = 9; + bmf.active_streams = 9; plr.looping = 1; } } -float -CxadbmfPlayer::xadplayer_getrefresh () +float CxadbmfPlayer::xadplayer_getrefresh() { return bmf.timer; } -std::string CxadbmfPlayer::xadplayer_gettype () +std::string CxadbmfPlayer::xadplayer_gettype() { - return std::string ("xad: BMF Adlib Tracker"); + return std::string("xad: BMF Adlib Tracker"); } -std::string CxadbmfPlayer::xadplayer_gettitle () +std::string CxadbmfPlayer::xadplayer_gettitle() { - return std::string (bmf.title); + return std::string(bmf.title); } -std::string CxadbmfPlayer::xadplayer_getauthor () +std::string CxadbmfPlayer::xadplayer_getauthor() { - return std::string (bmf.author); + return std::string(bmf.author); } -unsigned int -CxadbmfPlayer::xadplayer_getinstruments () +unsigned int CxadbmfPlayer::xadplayer_getinstruments() { return 32; } -std::string CxadbmfPlayer::xadplayer_getinstrument (unsigned int i) +std::string CxadbmfPlayer::xadplayer_getinstrument(unsigned int i) { - return std::string (bmf.instruments[i].name); + return std::string(bmf.instruments[i].name); } /* -------- Internal Functions ---------------------------- */ -int -CxadbmfPlayer::__bmf_convert_stream (unsigned char *stream, int channel) +int CxadbmfPlayer::__bmf_convert_stream(unsigned char *stream, int channel) { #ifdef DEBUG - AdPlug_LogWrite - ("channel %02X (note,delay,volume,instrument,command,command_data):\n", - channel); + AdPlug_LogWrite("channel %02X (note,delay,volume,instrument,command,command_data):\n",channel); unsigned char *last = stream; #endif unsigned char *stream_start = stream; @@ -457,63 +422,62 @@ CxadbmfPlayer::__bmf_convert_stream (unsigned char *stream, int channel) while (true) { - memset (&bmf.streams[channel][pos], 0, sizeof (bmf_event)); + memset(&bmf.streams[channel][pos], 0, sizeof(bmf_event)); bool is_cmd = false; if (*stream == 0xFE) - { + { // 0xFE -> 0xFF: End of Stream bmf.streams[channel][pos].cmd = 0xFF; - stream++; + stream++; break; - } + } else if (*stream == 0xFC) - { + { // 0xFC -> 0xFE xx: Save Loop Position bmf.streams[channel][pos].cmd = 0xFE; - bmf.streams[channel][pos].cmd_data = - (*(stream + 1) & ((bmf.version == BMF0_9B) ? 0x7F : 0x3F)) - 1; + bmf.streams[channel][pos].cmd_data = (*(stream+1) & ((bmf.version == BMF0_9B) ? 0x7F : 0x3F)) - 1; - stream += 2; + stream+=2; } else if (*stream == 0x7D) - { + { // 0x7D -> 0xFD: Loop Saved Position bmf.streams[channel][pos].cmd = 0xFD; - stream++; - } - else + stream++; + } + else { if (*stream & 0x80) { - if (*(stream + 1) & 0x80) + if (*(stream+1) & 0x80) { - if (*(stream + 1) & 0x40) + if (*(stream+1) & 0x40) { // byte0: 1aaaaaaa = NOTE bmf.streams[channel][pos].note = *stream & 0x7F; // byte1: 11bbbbbb = DELAY - bmf.streams[channel][pos].delay = *(stream + 1) & 0x3F; + bmf.streams[channel][pos].delay = *(stream+1) & 0x3F; // byte2: cccccccc = COMMAND - stream += 2; + stream+=2; is_cmd = true; } - else + else { // byte0: 1aaaaaaa = NOTE bmf.streams[channel][pos].note = *stream & 0x7F; // byte1: 11bbbbbb = DELAY - bmf.streams[channel][pos].delay = *(stream + 1) & 0x3F; + bmf.streams[channel][pos].delay = *(stream+1) & 0x3F; - stream += 2; - } // if (*(stream+1) & 0x40) - } + stream+=2; + } // if (*(stream+1) & 0x40) + } else { // byte0: 1aaaaaaa = NOTE @@ -523,18 +487,18 @@ CxadbmfPlayer::__bmf_convert_stream (unsigned char *stream, int channel) stream++; is_cmd = true; - } // if (*(stream+1) & 0x80) - } - else + } // if (*(stream+1) & 0x80) + } + else { // byte0: 0aaaaaaa = NOTE bmf.streams[channel][pos].note = *stream & 0x7F; - stream++; - } // if (*stream & 0x80) - } // if (*stream == 0xFE) + stream++; + } // if (*stream & 0x80) + } // if (*stream == 0xFE) - // is command ? + // is command ? if (is_cmd) { @@ -545,14 +509,14 @@ CxadbmfPlayer::__bmf_convert_stream (unsigned char *stream, int channel) // 0x20 or higher; 0x3F or lower: Set Instrument bmf.streams[channel][pos].instrument = *stream - 0x20 + 1; - stream++; + stream++; } else if (0x40 <= *stream) { // 0x40 or higher: Set Volume bmf.streams[channel][pos].volume = *stream - 0x40 + 1; - stream++; + stream++; } else { @@ -560,77 +524,78 @@ CxadbmfPlayer::__bmf_convert_stream (unsigned char *stream, int channel) /* 0.9b */ if (bmf.version == BMF0_9B) - if (*stream < 0x20) - { - // 0x1F or lower: ? - stream++; - } + if (*stream < 0x20) + { + // 0x1F or lower: ? + stream++; + } /* 1.2 */ if (bmf.version == BMF1_2) - { - if (*stream == 0x01) - { - // 0x01: Set Modulator Volume -> 0x01 - bmf.streams[channel][pos].cmd = 0x01; - bmf.streams[channel][pos].cmd_data = *(stream + 1); - - stream += 2; - } - else if (*stream == 0x02) - { - // 0x02: ? - stream += 2; - } - else if (*stream == 0x03) - { - // 0x03: ? - stream += 2; - } - else if (*stream == 0x04) - { - // 0x04: Set Speed -> 0x10 - bmf.streams[channel][pos].cmd = 0x10; - bmf.streams[channel][pos].cmd_data = *(stream + 1); - - stream += 2; - } - else if (*stream == 0x05) - { - // 0x05: Set Carrier Volume (port 380) - bmf.streams[channel][pos].volume = *(stream + 1) + 1; - - stream += 2; - } - else if (*stream == 0x06) - { - // 0x06: Set Carrier Volume (port 382) - bmf.streams[channel][pos].volume = *(stream + 1) + 1; - - stream += 2; - } - } // if (bmf.version == BMF1_2) - - } // if ((0x20 <= *stream) && (*stream <= 0x3F)) - - } // if (is_cmd) + { + if (*stream == 0x01) + { + // 0x01: Set Modulator Volume -> 0x01 + bmf.streams[channel][pos].cmd = 0x01; + bmf.streams[channel][pos].cmd_data = *(stream+1); + + stream+=2; + } + else if (*stream == 0x02) + { + // 0x02: ? + stream+=2; + } + else if (*stream == 0x03) + { + // 0x03: ? + stream+=2; + } + else if (*stream == 0x04) + { + // 0x04: Set Speed -> 0x10 + bmf.streams[channel][pos].cmd = 0x10; + bmf.streams[channel][pos].cmd_data = *(stream+1); + + stream+=2; + } + else if (*stream == 0x05) + { + // 0x05: Set Carrier Volume (port 380) + bmf.streams[channel][pos].volume = *(stream+1) + 1; + + stream+=2; + } + else if (*stream == 0x06) + { + // 0x06: Set Carrier Volume (port 382) + bmf.streams[channel][pos].volume = *(stream+1) + 1; + + stream+=2; + } + } // if (bmf.version == BMF1_2) + + } // if ((0x20 <= *stream) && (*stream <= 0x3F)) + + } // if (is_cmd) #ifdef DEBUG - AdPlug_LogWrite ("%02X %02X %02X %02X %02X %02X <---- ", - bmf.streams[channel][pos].note, - bmf.streams[channel][pos].delay, - bmf.streams[channel][pos].volume, - bmf.streams[channel][pos].instrument, - bmf.streams[channel][pos].cmd, - bmf.streams[channel][pos].cmd_data); - for (int zz = 0; zz < (stream - last); zz++) - AdPlug_LogWrite ("%02X ", last[zz]); - AdPlug_LogWrite ("\n"); - last = stream; + AdPlug_LogWrite("%02X %02X %02X %02X %02X %02X <---- ", + bmf.streams[channel][pos].note, + bmf.streams[channel][pos].delay, + bmf.streams[channel][pos].volume, + bmf.streams[channel][pos].instrument, + bmf.streams[channel][pos].cmd, + bmf.streams[channel][pos].cmd_data + ); + for(int zz=0;zz<(stream-last);zz++) + AdPlug_LogWrite("%02X ",last[zz]); + AdPlug_LogWrite("\n"); + last=stream; #endif pos++; - } // while (true) + } // while (true) return (stream - stream_start); } diff --git a/src/adplug/core/bmf.h b/src/adplug/core/bmf.h index f61a588..aa76969 100644 --- a/src/adplug/core/bmf.h +++ b/src/adplug/core/bmf.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -51,7 +51,7 @@ protected: char author[36]; float timer; unsigned char speed; - + struct { char name[11]; diff --git a/src/adplug/core/cff.cc b/src/adplug/core/cff.cc index 7bffae5..7fd45d6 100644 --- a/src/adplug/core/cff.cc +++ b/src/adplug/core/cff.cc @@ -1,6 +1,6 @@ /* AdPlug - Replayer for many OPL2/OPL3 audio file formats. - Copyright (C) 1999 - 2006 Simon Peter <dn.tlp@gmx.net>, et al. + Copyright (C) 1999 - 2008 Simon Peter <dn.tlp@gmx.net>, et al. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -24,6 +24,7 @@ slides use previous effect data instead of current. */ +#include <cstring> #include <stdlib.h> #include <string.h> @@ -31,286 +32,273 @@ /* -------- Public Methods -------------------------------- */ -CPlayer * -CcffLoader::factory (Copl * newopl) +CPlayer *CcffLoader::factory(Copl *newopl) { - return new CcffLoader (newopl); + return new CcffLoader(newopl); } -bool -CcffLoader::load (VFSFile & fd, const CFileProvider & fp) +bool CcffLoader::load(const std::string &filename, const CFileProvider &fp) { - binistream *f = fp.open (fd); - if (!f) - return false; - const unsigned char conv_inst[11] = { 2, 1, 10, 9, 4, 3, 6, 5, 0, 8, 7 }; - const unsigned short conv_note[12] = - { 0x16B, 0x181, 0x198, 0x1B0, 0x1CA, 0x1E5, 0x202, 0x220, 0x241, 0x263, -0x287, 0x2AE }; + binistream *f = fp.open(filename); if(!f) return false; + const unsigned char conv_inst[11] = { 2,1,10,9,4,3,6,5,0,8,7 }; + const unsigned short conv_note[12] = { 0x16B, 0x181, 0x198, 0x1B0, 0x1CA, 0x1E5, 0x202, 0x220, 0x241, 0x263, 0x287, 0x2AE }; - int i, j, k, t = 0; + int i,j,k,t=0; // '<CUD-FM-File>' - signed ? - f->readString (header.id, 16); - header.version = f->readInt (1); - header.size = f->readInt (2); - header.packed = f->readInt (1); - f->readString ((char *) header.reserved, 12); - if (memcmp (header.id, "<CUD-FM-File>" "\x1A\xDE\xE0", 16)) - { - fp.close (f); - return false; - } + f->readString(header.id, 16); + header.version = f->readInt(1); header.size = f->readInt(2); + header.packed = f->readInt(1); f->readString((char *)header.reserved, 12); + if (memcmp(header.id,"<CUD-FM-File>""\x1A\xDE\xE0",16)) + { fp.close(f); return false; } - unsigned char *module = new unsigned char[0x10000]; + unsigned char *module = new unsigned char [0x10000]; // packed ? if (header.packed) - { - cff_unpacker *unpacker = new cff_unpacker; + { + cff_unpacker *unpacker = new cff_unpacker; - unsigned char *packed_module = new unsigned char[header.size + 4]; + unsigned char *packed_module = new unsigned char [header.size + 4]; - memset (packed_module, 0, header.size + 4); + memset(packed_module,0,header.size + 4); - f->readString ((char *) packed_module, header.size); - fp.close (f); + f->readString((char *)packed_module, header.size); + fp.close(f); - if (!unpacker->unpack (packed_module, module)) - { - delete unpacker; - delete[] packed_module; - delete[] module; - return false; - } + if (!unpacker->unpack(packed_module,module)) + { + delete unpacker; + delete [] packed_module; + delete [] module; + return false; + } - delete unpacker; - delete[] packed_module; + delete unpacker; + delete [] packed_module; - if (memcmp (&module[0x5E1], "CUD-FM-File - SEND A POSTCARD -", 31)) - { - delete[] module; - return false; + if (memcmp(&module[0x5E1],"CUD-FM-File - SEND A POSTCARD -",31)) + { + delete [] module; + return false; + } } - } else - { - f->readString ((char *) module, header.size); - fp.close (f); - } + { + f->readString((char *)module, header.size); + fp.close(f); + } // init CmodPlayer - realloc_instruments (47); - realloc_order (64); - realloc_patterns (36, 64, 9); - init_notetable (conv_note); - init_trackord (); + realloc_instruments(47); + realloc_order(64); + realloc_patterns(36,64,9); + init_notetable(conv_note); + init_trackord(); // load instruments - for (i = 0; i < 47; i++) - { - memcpy (&instruments[i], &module[i * 32], sizeof (cff_instrument)); + for (i=0;i<47;i++) + { + memcpy(&instruments[i],&module[i*32],sizeof(cff_instrument)); - for (j = 0; j < 11; j++) - inst[i].data[conv_inst[j]] = instruments[i].data[j]; + for (j=0;j<11;j++) + inst[i].data[conv_inst[j]] = instruments[i].data[j]; - instruments[i].name[20] = 0; - } + instruments[i].name[20] = 0; + } // number of patterns nop = module[0x5E0]; // load title & author - memcpy (song_title, &module[0x614], 20); - memcpy (song_author, &module[0x600], 20); + memcpy(song_title,&module[0x614],20); + memcpy(song_author,&module[0x600],20); // load order - memcpy (order, &module[0x628], 64); + memcpy(order,&module[0x628],64); // load tracks - for (i = 0; i < nop; i++) - { - unsigned char old_event_byte2[9]; - - memset (old_event_byte2, 0, 9); - - for (j = 0; j < 9; j++) + for (i=0;i<nop;i++) { - for (k = 0; k < 64; k++) - { - cff_event *event = - (cff_event *) & module[0x669 + ((i * 64 + k) * 9 + j) * 3]; - - // convert note - if (event->byte0 == 0x6D) - tracks[t][k].note = 127; - else if (event->byte0) - tracks[t][k].note = event->byte0; - - if (event->byte2) - old_event_byte2[j] = event->byte2; - - // convert effect - switch (event->byte1) - { - case 'I': // set instrument - tracks[t][k].inst = event->byte2 + 1; - tracks[t][k].param1 = tracks[t][k].param2 = 0; - break; - - case 'H': // set tempo - tracks[t][k].command = 7; - if (event->byte2 < 16) - { - tracks[t][k].param1 = 0x07; - tracks[t][k].param2 = 0x0D; - } - break; - - case 'A': // set speed - tracks[t][k].command = 19; - tracks[t][k].param1 = event->byte2 >> 4; - tracks[t][k].param2 = event->byte2 & 15; - break; - - case 'L': // pattern break - tracks[t][k].command = 13; - tracks[t][k].param1 = event->byte2 >> 4; - tracks[t][k].param2 = event->byte2 & 15; - break; - - case 'K': // order jump - tracks[t][k].command = 11; - tracks[t][k].param1 = event->byte2 >> 4; - tracks[t][k].param2 = event->byte2 & 15; - break; - - case 'M': // set vibrato/tremolo - tracks[t][k].command = 27; - tracks[t][k].param1 = event->byte2 >> 4; - tracks[t][k].param2 = event->byte2 & 15; - break; - - case 'C': // set modulator volume - tracks[t][k].command = 21; - tracks[t][k].param1 = (0x3F - event->byte2) >> 4; - tracks[t][k].param2 = (0x3F - event->byte2) & 15; - break; - - case 'G': // set carrier volume - tracks[t][k].command = 22; - tracks[t][k].param1 = (0x3F - event->byte2) >> 4; - tracks[t][k].param2 = (0x3F - event->byte2) & 15; - break; - - case 'B': // set carrier waveform - tracks[t][k].command = 25; - tracks[t][k].param1 = event->byte2; - tracks[t][k].param2 = 0x0F; - break; + unsigned char old_event_byte2[9]; - case 'E': // fine frequency slide down - tracks[t][k].command = 24; - tracks[t][k].param1 = old_event_byte2[j] >> 4; - tracks[t][k].param2 = old_event_byte2[j] & 15; - break; - - case 'F': // fine frequency slide up - tracks[t][k].command = 23; - tracks[t][k].param1 = old_event_byte2[j] >> 4; - tracks[t][k].param2 = old_event_byte2[j] & 15; - break; - - case 'D': // fine volume slide - tracks[t][k].command = 14; - if (old_event_byte2[j] & 15) - { - // slide down - tracks[t][k].param1 = 5; - tracks[t][k].param2 = old_event_byte2[j] & 15; - } - else - { - // slide up - tracks[t][k].param1 = 4; - tracks[t][k].param2 = old_event_byte2[j] >> 4; - } - break; + memset(old_event_byte2,0,9); - case 'J': // arpeggio - tracks[t][k].param1 = old_event_byte2[j] >> 4; - tracks[t][k].param2 = old_event_byte2[j] & 15; - break; + for (j=0;j<9;j++) + { + for (k=0;k<64;k++) + { + cff_event *event = (cff_event *)&module[0x669 + ((i*64+k)*9+j)*3]; + + // convert note + if (event->byte0 == 0x6D) + tracks[t][k].note = 127; + else + if (event->byte0) + tracks[t][k].note = event->byte0; + + if (event->byte2) + old_event_byte2[j] = event->byte2; + + // convert effect + switch (event->byte1) + { + case 'I': // set instrument + tracks[t][k].inst = event->byte2 + 1; + tracks[t][k].param1 = tracks[t][k].param2 = 0; + break; + + case 'H': // set tempo + tracks[t][k].command = 7; + if (event->byte2 < 16) + { + tracks[t][k].param1 = 0x07; + tracks[t][k].param2 = 0x0D; + } + break; + + case 'A': // set speed + tracks[t][k].command = 19; + tracks[t][k].param1 = event->byte2 >> 4; + tracks[t][k].param2 = event->byte2 & 15; + break; + + case 'L': // pattern break + tracks[t][k].command = 13; + tracks[t][k].param1 = event->byte2 >> 4; + tracks[t][k].param2 = event->byte2 & 15; + break; + + case 'K': // order jump + tracks[t][k].command = 11; + tracks[t][k].param1 = event->byte2 >> 4; + tracks[t][k].param2 = event->byte2 & 15; + break; + + case 'M': // set vibrato/tremolo + tracks[t][k].command = 27; + tracks[t][k].param1 = event->byte2 >> 4; + tracks[t][k].param2 = event->byte2 & 15; + break; + + case 'C': // set modulator volume + tracks[t][k].command = 21; + tracks[t][k].param1 = (0x3F - event->byte2) >> 4; + tracks[t][k].param2 = (0x3F - event->byte2) & 15; + break; + + case 'G': // set carrier volume + tracks[t][k].command = 22; + tracks[t][k].param1 = (0x3F - event->byte2) >> 4; + tracks[t][k].param2 = (0x3F - event->byte2) & 15; + break; + + case 'B': // set carrier waveform + tracks[t][k].command = 25; + tracks[t][k].param1 = event->byte2; + tracks[t][k].param2 = 0x0F; + break; + + case 'E': // fine frequency slide down + tracks[t][k].command = 24; + tracks[t][k].param1 = old_event_byte2[j] >> 4; + tracks[t][k].param2 = old_event_byte2[j] & 15; + break; + + case 'F': // fine frequency slide up + tracks[t][k].command = 23; + tracks[t][k].param1 = old_event_byte2[j] >> 4; + tracks[t][k].param2 = old_event_byte2[j] & 15; + break; + + case 'D': // fine volume slide + tracks[t][k].command = 14; + if (old_event_byte2[j] & 15) + { + // slide down + tracks[t][k].param1 = 5; + tracks[t][k].param2 = old_event_byte2[j] & 15; + } + else + { + // slide up + tracks[t][k].param1 = 4; + tracks[t][k].param2 = old_event_byte2[j] >> 4; + } + break; + + case 'J': // arpeggio + tracks[t][k].param1 = old_event_byte2[j] >> 4; + tracks[t][k].param2 = old_event_byte2[j] & 15; + break; + } + } + + t++; } - } - - t++; } - } - delete[]module; + delete [] module; // order loop restartpos = 0; // order length - for (i = 0; i < 64; i++) - { - if (order[i] >= 0x80) + for (i=0;i<64;i++) { - length = i; - break; + if (order[i] >= 0x80) + { + length = i; + break; + } } - } // default tempo bpm = 0x7D; - rewind (0); + rewind(0); return true; } -void -CcffLoader::rewind (int subsong) +void CcffLoader::rewind(int subsong) { - CmodPlayer::rewind (subsong); + CmodPlayer::rewind(subsong); // default instruments - for (int i = 0; i < 9; i++) - { - channel[i].inst = i; + for (int i=0;i<9;i++) + { + channel[i].inst = i; - channel[i].vol1 = 63 - (inst[i].data[10] & 63); - channel[i].vol2 = 63 - (inst[i].data[9] & 63); - } + channel[i].vol1 = 63 - (inst[i].data[10] & 63); + channel[i].vol2 = 63 - (inst[i].data[9] & 63); + } } -std::string CcffLoader::gettype () +std::string CcffLoader::gettype() { if (header.packed) - return std::string ("BoomTracker 4, packed"); + return std::string("BoomTracker 4, packed"); else - return std::string ("BoomTracker 4"); + return std::string("BoomTracker 4"); } -std::string CcffLoader::gettitle () +std::string CcffLoader::gettitle() { - return std::string (song_title, 20); + return std::string(song_title,20); } -std::string CcffLoader::getauthor () +std::string CcffLoader::getauthor() { - return std::string (song_author, 20); + return std::string(song_author,20); } -std::string CcffLoader::getinstrument (unsigned int n) +std::string CcffLoader::getinstrument(unsigned int n) { - return std::string (instruments[n].name); + return std::string(instruments[n].name); } -unsigned int -CcffLoader::getinstruments () +unsigned int CcffLoader::getinstruments() { return 47; } @@ -320,10 +308,9 @@ CcffLoader::getinstruments () /* Lempel-Ziv-Tyr ;-) */ -long -CcffLoader::cff_unpacker::unpack (unsigned char *ibuf, unsigned char *obuf) +long CcffLoader::cff_unpacker::unpack(unsigned char *ibuf, unsigned char *obuf) { - if (memcmp (ibuf, "YsComp" "\x07" "CUD1997" "\x1A\x04", 16)) + if (memcmp(ibuf,"YsComp""\x07""CUD1997""\x1A\x04",16)) return 0; input = ibuf + 16; @@ -331,129 +318,120 @@ CcffLoader::cff_unpacker::unpack (unsigned char *ibuf, unsigned char *obuf) output_length = 0; - heap = (unsigned char *) malloc (0x10000); - dictionary = (unsigned char **) malloc (sizeof (unsigned char *) * 0x8000); + heap = (unsigned char *)malloc(0x10000); + dictionary = (unsigned char **)malloc(sizeof(unsigned char *)*0x8000); - memset (heap, 0, 0x10000); - memset (dictionary, 0, 0x8000); + memset(heap,0,0x10000); + memset(dictionary,0,0x8000); - cleanup (); - if (!startup ()) + cleanup(); + if(!startup()) goto out; // LZW while (1) - { - new_code = get_code (); + { + new_code = get_code(); - // 0x00: end of data - if (new_code == 0) - break; + // 0x00: end of data + if (new_code == 0) + break; - // 0x01: end of block - if (new_code == 1) - { - cleanup (); - if (!startup ()) - goto out; + // 0x01: end of block + if (new_code == 1) + { + cleanup(); + if(!startup()) + goto out; - continue; - } + continue; + } - // 0x02: expand code length - if (new_code == 2) - { - code_length++; + // 0x02: expand code length + if (new_code == 2) + { + code_length++; - continue; - } + continue; + } - // 0x03: RLE - if (new_code == 3) - { - unsigned char - old_code_length = code_length; + // 0x03: RLE + if (new_code == 3) + { + unsigned char old_code_length = code_length; - code_length = 2; + code_length = 2; - unsigned char - repeat_length = get_code () + 1; + unsigned char repeat_length = get_code() + 1; - code_length = 4 << get_code (); + code_length = 4 << get_code(); - unsigned long - repeat_counter = get_code (); + unsigned long repeat_counter = get_code(); - if (output_length + repeat_counter * repeat_length > 0x10000) - { - output_length = 0; - goto out; - } + if(output_length + repeat_counter * repeat_length > 0x10000) { + output_length = 0; + goto out; + } - for (unsigned int i = 0; i < repeat_counter * repeat_length; i++) - { - output[output_length] = output[output_length - repeat_length]; - output_length++; - } + for (unsigned int i=0;i<repeat_counter*repeat_length;i++) { + output[output_length] = output[output_length - repeat_length]; + output_length++; + } - code_length = old_code_length; + code_length = old_code_length; - if (!startup ()) - goto out; + if(!startup()) + goto out; - continue; - } + continue; + } - if (new_code >= (0x104 + dictionary_length)) - { - // dictionary <- old.code.string + old.code.char - the_string[++the_string[0]] = the_string[1]; - } - else - { - // dictionary <- old.code.string + new.code.char - unsigned char - temp_string[256]; + if (new_code >= (0x104 + dictionary_length)) + { + // dictionary <- old.code.string + old.code.char + the_string[++the_string[0]] = the_string[1]; + } + else + { + // dictionary <- old.code.string + new.code.char + unsigned char temp_string[256]; - translate_code (new_code, temp_string); + translate_code(new_code,temp_string); - the_string[++the_string[0]] = temp_string[1]; - } + the_string[++the_string[0]] = temp_string[1]; + } - expand_dictionary (the_string); + expand_dictionary(the_string); - // output <- new.code.string - translate_code (new_code, the_string); + // output <- new.code.string + translate_code(new_code,the_string); - if (output_length + the_string[0] > 0x10000) - { - output_length = 0; - goto out; - } + if(output_length + the_string[0] > 0x10000) { + output_length = 0; + goto out; + } - for (int i = 0; i < the_string[0]; i++) - output[output_length++] = the_string[i + 1]; + for (int i=0;i<the_string[0];i++) + output[output_length++] = the_string[i+1]; - old_code = new_code; - } + old_code = new_code; + } -out: - free (heap); - free (dictionary); + out: + free(heap); + free(dictionary); return output_length; } -unsigned long -CcffLoader::cff_unpacker::get_code () +unsigned long CcffLoader::cff_unpacker::get_code() { - unsigned long - code; + unsigned long code; while (bits_left < code_length) - { - bits_buffer |= ((*input++) << bits_left); - bits_left += 8; - } + { + bits_buffer |= ((*input++) << bits_left); + bits_left += 8; + } code = bits_buffer & ((1 << code_length) - 1); @@ -463,29 +441,24 @@ CcffLoader::cff_unpacker::get_code () return code; } -void -CcffLoader::cff_unpacker::translate_code (unsigned long code, - unsigned char *string) +void CcffLoader::cff_unpacker::translate_code(unsigned long code, unsigned char *string) { - unsigned char - translated_string[256]; + unsigned char translated_string[256]; if (code >= 0x104) - { - memcpy (translated_string, dictionary[code - 0x104], - (*(dictionary[code - 0x104])) + 1); - } + { + memcpy(translated_string,dictionary[code - 0x104],(*(dictionary[code - 0x104])) + 1); + } else - { - translated_string[0] = 1; - translated_string[1] = (code - 4) & 0xFF; - } + { + translated_string[0] = 1; + translated_string[1] = (code - 4) & 0xFF; + } - memcpy (string, translated_string, 256); + memcpy(string,translated_string,256); } -void -CcffLoader::cff_unpacker::cleanup () +void CcffLoader::cff_unpacker::cleanup() { code_length = 9; @@ -496,32 +469,29 @@ CcffLoader::cff_unpacker::cleanup () dictionary_length = 0; } -int -CcffLoader::cff_unpacker::startup () +int CcffLoader::cff_unpacker::startup() { - old_code = get_code (); + old_code = get_code(); - translate_code (old_code, the_string); + translate_code(old_code,the_string); - if (output_length + the_string[0] > 0x10000) - { + if(output_length + the_string[0] > 0x10000) { output_length = 0; return 0; } - for (int i = 0; i < the_string[0]; i++) - output[output_length++] = the_string[i + 1]; + for (int i=0;i<the_string[0];i++) + output[output_length++] = the_string[i+1]; return 1; } -void -CcffLoader::cff_unpacker::expand_dictionary (unsigned char *string) +void CcffLoader::cff_unpacker::expand_dictionary(unsigned char *string) { if (string[0] >= 0xF0) return; - memcpy (&heap[heap_length], string, string[0] + 1); + memcpy(&heap[heap_length],string,string[0] + 1); dictionary[dictionary_length] = &heap[heap_length]; diff --git a/src/adplug/core/cff.h b/src/adplug/core/cff.h index 3cdff6e..ed593b9 100644 --- a/src/adplug/core/cff.h +++ b/src/adplug/core/cff.h @@ -23,81 +23,81 @@ class CcffLoader: public CmodPlayer { - public: - static CPlayer *factory(Copl *newopl); + public: + static CPlayer *factory(Copl *newopl); - CcffLoader(Copl *newopl) : CmodPlayer(newopl) { }; + CcffLoader(Copl *newopl) : CmodPlayer(newopl) { }; - bool load(VFSFile &fd, const CFileProvider &fp); - void rewind(int subsong); + bool load(const std::string &filename, const CFileProvider &fp); + void rewind(int subsong); - std::string gettype(); - std::string gettitle(); - std::string getauthor(); - std::string getinstrument(unsigned int n); - unsigned int getinstruments(); + std::string gettype(); + std::string gettitle(); + std::string getauthor(); + std::string getinstrument(unsigned int n); + unsigned int getinstruments(); - private: + private: - class cff_unpacker - { - public: + class cff_unpacker + { + public: - long unpack(unsigned char *ibuf, unsigned char *obuf); + long unpack(unsigned char *ibuf, unsigned char *obuf); - private: + private: - unsigned long get_code(); - void translate_code(unsigned long code, unsigned char *string); + unsigned long get_code(); + void translate_code(unsigned long code, unsigned char *string); - void cleanup(); - int startup(); + void cleanup(); + int startup(); - void expand_dictionary(unsigned char *string); + void expand_dictionary(unsigned char *string); - unsigned char *input; - unsigned char *output; + unsigned char *input; + unsigned char *output; - long output_length; + long output_length; - unsigned char code_length; + unsigned char code_length; - unsigned long bits_buffer; - unsigned int bits_left; + unsigned long bits_buffer; + unsigned int bits_left; - unsigned char *heap; - unsigned char **dictionary; + unsigned char *heap; + unsigned char **dictionary; - unsigned int heap_length; - unsigned int dictionary_length; + unsigned int heap_length; + unsigned int dictionary_length; - unsigned long old_code,new_code; + unsigned long old_code,new_code; - unsigned char the_string[256]; - }; + unsigned char the_string[256]; + }; - struct cff_header - { - char id[16]; - unsigned char version; - unsigned short size; - unsigned char packed; - unsigned char reserved[12]; - } header; + struct cff_header + { + char id[16]; + unsigned char version; + unsigned short size; + unsigned char packed; + unsigned char reserved[12]; + } header; - struct cff_instrument - { - unsigned char data[12]; - char name[21]; - } instruments[47]; + struct cff_instrument + { + unsigned char data[12]; + char name[21]; + } instruments[47]; - char song_title[20]; - char song_author[20]; + char song_title[20]; + char song_author[20]; - struct cff_event - { - unsigned char byte0; - unsigned char byte1; - unsigned char byte2; - }; + struct cff_event + { + unsigned char byte0; + unsigned char byte1; + unsigned char byte2; + }; }; diff --git a/src/adplug/core/cmf.cc b/src/adplug/core/cmf.cc index 21f3490..c9a0fd4 100644 --- a/src/adplug/core/cmf.cc +++ b/src/adplug/core/cmf.cc @@ -89,313 +89,312 @@ CPlayer *CcmfPlayer::factory(Copl *newopl) } CcmfPlayer::CcmfPlayer(Copl *newopl) : - CPlayer(newopl), - data(nullptr), - pInstruments(nullptr), - bPercussive(false), - iTranspose(0), - iPrevCommand(0) + CPlayer(newopl), + data(NULL), + pInstruments(NULL), + bPercussive(false), + iTranspose(0), + iPrevCommand(0) { - assert(OPLOFFSET(1-1) == 0x00); - assert(OPLOFFSET(5-1) == 0x09); - assert(OPLOFFSET(9-1) == 0x12); + assert(OPLOFFSET(1-1) == 0x00); + assert(OPLOFFSET(5-1) == 0x09); + assert(OPLOFFSET(9-1) == 0x12); } CcmfPlayer::~CcmfPlayer() { - if (this->data) delete[] data; - if (this->pInstruments) delete[] pInstruments; + if (this->data) delete[] data; + if (this->pInstruments) delete[] pInstruments; } -bool CcmfPlayer::load(VFSFile & fd, const CFileProvider &fp) +bool CcmfPlayer::load(const std::string &filename, const CFileProvider &fp) { - binistream *f = fp.open(fd); - if(!f) return false; - - char cSig[4]; - f->readString(cSig, 4); - if ( - (cSig[0] != 'C') || - (cSig[1] != 'T') || - (cSig[2] != 'M') || - (cSig[3] != 'F') - ) { - // Not a CMF file - fp.close(f); - return false; - } - uint16_t iVer = f->readInt(2); - if ((iVer != 0x0101) && (iVer != 0x0100)) { - AdPlug_LogWrite("CMF file is not v1.0 or v1.1 (reports %d.%d)\n", iVer >> 8 , iVer & 0xFF); - fp.close(f); - return false; - } - - this->cmfHeader.iInstrumentBlockOffset = f->readInt(2); - this->cmfHeader.iMusicOffset = f->readInt(2); - this->cmfHeader.iTicksPerQuarterNote = f->readInt(2); - this->cmfHeader.iTicksPerSecond = f->readInt(2); - this->cmfHeader.iTagOffsetTitle = f->readInt(2); - this->cmfHeader.iTagOffsetComposer = f->readInt(2); - this->cmfHeader.iTagOffsetRemarks = f->readInt(2); - f->readString((char *)this->cmfHeader.iChannelsInUse, 16); - if (iVer == 0x0100) { - this->cmfHeader.iNumInstruments = f->readInt(1); - this->cmfHeader.iTempo = 0; - } else { // 0x0101 - this->cmfHeader.iNumInstruments = f->readInt(2); - this->cmfHeader.iTempo = f->readInt(2); - } - - // Load the instruments - - f->seek(this->cmfHeader.iInstrumentBlockOffset); - this->pInstruments = new SBI[ - (this->cmfHeader.iNumInstruments < 128) ? 128 : this->cmfHeader.iNumInstruments - ]; // Always at least 128 available for use - - for (int i = 0; i < this->cmfHeader.iNumInstruments; i++) { - this->pInstruments[i].op[0].iCharMult = f->readInt(1); - this->pInstruments[i].op[1].iCharMult = f->readInt(1); - this->pInstruments[i].op[0].iScalingOutput = f->readInt(1); - this->pInstruments[i].op[1].iScalingOutput = f->readInt(1); - this->pInstruments[i].op[0].iAttackDecay = f->readInt(1); - this->pInstruments[i].op[1].iAttackDecay = f->readInt(1); - this->pInstruments[i].op[0].iSustainRelease = f->readInt(1); - this->pInstruments[i].op[1].iSustainRelease = f->readInt(1); - this->pInstruments[i].op[0].iWaveSel = f->readInt(1); - this->pInstruments[i].op[1].iWaveSel = f->readInt(1); - this->pInstruments[i].iConnection = f->readInt(1); - f->seek(5, binio::Add); // skip over the padding bytes - } - - // Set the rest of the instruments to the CMF defaults - for (int i = this->cmfHeader.iNumInstruments; i < 128; i++) { - this->pInstruments[i].op[0].iCharMult = cDefaultPatches[(i % 16) * 11 + 0]; - this->pInstruments[i].op[1].iCharMult = cDefaultPatches[(i % 16) * 11 + 1]; - this->pInstruments[i].op[0].iScalingOutput = cDefaultPatches[(i % 16) * 11 + 2]; - this->pInstruments[i].op[1].iScalingOutput = cDefaultPatches[(i % 16) * 11 + 3]; - this->pInstruments[i].op[0].iAttackDecay = cDefaultPatches[(i % 16) * 11 + 4]; - this->pInstruments[i].op[1].iAttackDecay = cDefaultPatches[(i % 16) * 11 + 5]; - this->pInstruments[i].op[0].iSustainRelease = cDefaultPatches[(i % 16) * 11 + 6]; - this->pInstruments[i].op[1].iSustainRelease = cDefaultPatches[(i % 16) * 11 + 7]; - this->pInstruments[i].op[0].iWaveSel = cDefaultPatches[(i % 16) * 11 + 8]; - this->pInstruments[i].op[1].iWaveSel = cDefaultPatches[(i % 16) * 11 + 9]; - this->pInstruments[i].iConnection = cDefaultPatches[(i % 16) * 11 + 10]; - } - - if (this->cmfHeader.iTagOffsetTitle) { - f->seek(this->cmfHeader.iTagOffsetTitle); - this->strTitle = f->readString('\0'); - } - if (this->cmfHeader.iTagOffsetComposer) { - f->seek(this->cmfHeader.iTagOffsetComposer); - this->strComposer = f->readString('\0'); - } - if (this->cmfHeader.iTagOffsetRemarks) { - f->seek(this->cmfHeader.iTagOffsetRemarks); - this->strRemarks = f->readString('\0'); - } - - // Load the MIDI data into memory + binistream *f = fp.open(filename); if(!f) return false; + + char cSig[4]; + f->readString(cSig, 4); + if ( + (cSig[0] != 'C') || + (cSig[1] != 'T') || + (cSig[2] != 'M') || + (cSig[3] != 'F') + ) { + // Not a CMF file + fp.close(f); + return false; + } + uint16_t iVer = f->readInt(2); + if ((iVer != 0x0101) && (iVer != 0x0100)) { + AdPlug_LogWrite("CMF file is not v1.0 or v1.1 (reports %d.%d)\n", iVer >> 8 , iVer & 0xFF); + fp.close(f); + return false; + } + + this->cmfHeader.iInstrumentBlockOffset = f->readInt(2); + this->cmfHeader.iMusicOffset = f->readInt(2); + this->cmfHeader.iTicksPerQuarterNote = f->readInt(2); + this->cmfHeader.iTicksPerSecond = f->readInt(2); + this->cmfHeader.iTagOffsetTitle = f->readInt(2); + this->cmfHeader.iTagOffsetComposer = f->readInt(2); + this->cmfHeader.iTagOffsetRemarks = f->readInt(2); + f->readString((char *)this->cmfHeader.iChannelsInUse, 16); + if (iVer == 0x0100) { + this->cmfHeader.iNumInstruments = f->readInt(1); + this->cmfHeader.iTempo = 0; + } else { // 0x0101 + this->cmfHeader.iNumInstruments = f->readInt(2); + this->cmfHeader.iTempo = f->readInt(2); + } + + // Load the instruments + + f->seek(this->cmfHeader.iInstrumentBlockOffset); + this->pInstruments = new SBI[ + (this->cmfHeader.iNumInstruments < 128) ? 128 : this->cmfHeader.iNumInstruments + ]; // Always at least 128 available for use + + for (int i = 0; i < this->cmfHeader.iNumInstruments; i++) { + this->pInstruments[i].op[0].iCharMult = f->readInt(1); + this->pInstruments[i].op[1].iCharMult = f->readInt(1); + this->pInstruments[i].op[0].iScalingOutput = f->readInt(1); + this->pInstruments[i].op[1].iScalingOutput = f->readInt(1); + this->pInstruments[i].op[0].iAttackDecay = f->readInt(1); + this->pInstruments[i].op[1].iAttackDecay = f->readInt(1); + this->pInstruments[i].op[0].iSustainRelease = f->readInt(1); + this->pInstruments[i].op[1].iSustainRelease = f->readInt(1); + this->pInstruments[i].op[0].iWaveSel = f->readInt(1); + this->pInstruments[i].op[1].iWaveSel = f->readInt(1); + this->pInstruments[i].iConnection = f->readInt(1); + f->seek(5, binio::Add); // skip over the padding bytes + } + + // Set the rest of the instruments to the CMF defaults + for (int i = this->cmfHeader.iNumInstruments; i < 128; i++) { + this->pInstruments[i].op[0].iCharMult = cDefaultPatches[(i % 16) * 11 + 0]; + this->pInstruments[i].op[1].iCharMult = cDefaultPatches[(i % 16) * 11 + 1]; + this->pInstruments[i].op[0].iScalingOutput = cDefaultPatches[(i % 16) * 11 + 2]; + this->pInstruments[i].op[1].iScalingOutput = cDefaultPatches[(i % 16) * 11 + 3]; + this->pInstruments[i].op[0].iAttackDecay = cDefaultPatches[(i % 16) * 11 + 4]; + this->pInstruments[i].op[1].iAttackDecay = cDefaultPatches[(i % 16) * 11 + 5]; + this->pInstruments[i].op[0].iSustainRelease = cDefaultPatches[(i % 16) * 11 + 6]; + this->pInstruments[i].op[1].iSustainRelease = cDefaultPatches[(i % 16) * 11 + 7]; + this->pInstruments[i].op[0].iWaveSel = cDefaultPatches[(i % 16) * 11 + 8]; + this->pInstruments[i].op[1].iWaveSel = cDefaultPatches[(i % 16) * 11 + 9]; + this->pInstruments[i].iConnection = cDefaultPatches[(i % 16) * 11 + 10]; + } + + if (this->cmfHeader.iTagOffsetTitle) { + f->seek(this->cmfHeader.iTagOffsetTitle); + this->strTitle = f->readString('\0'); + } + if (this->cmfHeader.iTagOffsetComposer) { + f->seek(this->cmfHeader.iTagOffsetComposer); + this->strComposer = f->readString('\0'); + } + if (this->cmfHeader.iTagOffsetRemarks) { + f->seek(this->cmfHeader.iTagOffsetRemarks); + this->strRemarks = f->readString('\0'); + } + + // Load the MIDI data into memory f->seek(this->cmfHeader.iMusicOffset); this->iSongLen = fp.filesize(f) - this->cmfHeader.iMusicOffset; this->data = new unsigned char[this->iSongLen]; f->readString((char *)data, this->iSongLen); fp.close(f); - rewind(0); + rewind(0); return true; } bool CcmfPlayer::update() { - // This has to be here and not in getrefresh() for some reason. - this->iDelayRemaining = 0; - - // Read in the next event - while (!this->iDelayRemaining) { - uint8_t iCommand = this->data[this->iPlayPointer++]; - if ((iCommand & 0x80) == 0) { - // Running status, use previous command - this->iPlayPointer--; - iCommand = this->iPrevCommand; - } else { - this->iPrevCommand = iCommand; - } - uint8_t iChannel = iCommand & 0x0F; - switch (iCommand & 0xF0) { - case 0x80: { // Note off (two data bytes) - uint8_t iNote = this->data[this->iPlayPointer++]; - uint8_t iVelocity = this->data[this->iPlayPointer++]; // release velocity - this->cmfNoteOff(iChannel, iNote, iVelocity); - break; - } - case 0x90: { // Note on (two data bytes) - uint8_t iNote = this->data[this->iPlayPointer++]; - uint8_t iVelocity = this->data[this->iPlayPointer++]; // attack velocity - if (iVelocity) { - this->cmfNoteOn(iChannel, iNote, iVelocity); - } else { - // This is a note-off instead (velocity == 0) - this->cmfNoteOff(iChannel, iNote, iVelocity); // 64 is the MIDI default note-off velocity - break; - } - break; - } - case 0xA0: { // Polyphonic key pressure (two data bytes) - uint8_t iNote = this->data[this->iPlayPointer++]; - uint8_t iPressure = this->data[this->iPlayPointer++]; - AdPlug_LogWrite("CMF: Key pressure not yet implemented! (wanted ch%d/note %d set to %d)\n", iChannel, iNote, iPressure); - break; - } - case 0xB0: { // Controller (two data bytes) - uint8_t iController = this->data[this->iPlayPointer++]; - uint8_t iValue = this->data[this->iPlayPointer++]; - this->MIDIcontroller(iChannel, iController, iValue); - break; - } - case 0xC0: { // Instrument change (one data byte) - uint8_t iNewInstrument = this->data[this->iPlayPointer++]; - this->chMIDI[iChannel].iPatch = iNewInstrument; - AdPlug_LogWrite("CMF: Remembering MIDI channel %d now uses patch %d\n", iChannel, iNewInstrument); - break; - } - case 0xD0: { // Channel pressure (one data byte) - uint8_t iPressure = this->data[this->iPlayPointer++]; - AdPlug_LogWrite("CMF: Channel pressure not yet implemented! (wanted ch%d set to %d)\n", iChannel, iPressure); - break; - } - case 0xE0: { // Pitch bend (two data bytes) - uint8_t iLSB = this->data[this->iPlayPointer++]; - uint8_t iMSB = this->data[this->iPlayPointer++]; - uint16_t iValue = (iMSB << 7) | iLSB; - // 8192 is middle/off, 0 is -2 semitones, 16384 is +2 semitones - this->chMIDI[iChannel].iPitchbend = iValue; - AdPlug_LogWrite("CMF: Channel %d pitchbent to %d (%+.2f)\n", iChannel + 1, iValue, (float)(iValue - 8192) / 8192); - break; - } - case 0xF0: // System message (arbitrary data bytes) - switch (iCommand) { - case 0xF0: { // Sysex - uint8_t iNextByte; - AdPlug_LogWrite("Sysex message: "); - do { - iNextByte = this->data[this->iPlayPointer++]; - AdPlug_LogWrite("%02X", iNextByte); - } while ((iNextByte & 0x80) == 0); - AdPlug_LogWrite("\n"); - // This will have read in the terminating EOX (0xF7) message too - break; - } - case 0xF1: // MIDI Time Code Quarter Frame - this->iPlayPointer++; // message data (ignored) - break; - case 0xF2: // Song position pointer - this->iPlayPointer++; // message data (ignored) - this->iPlayPointer++; - break; - case 0xF3: // Song select - this->iPlayPointer++; // message data (ignored) - AdPlug_LogWrite("CMF: MIDI Song Select is not implemented.\n"); - break; - case 0xF6: // Tune request - break; - case 0xF7: // End of System Exclusive (EOX) - should never be read, should be absorbed by Sysex handling code - break; - - // These messages are "real time", meaning they can be sent between - // the bytes of other messages - but we're lazy and don't handle these - // here (hopefully they're not necessary in a MIDI file, and even less - // likely to occur in a CMF.) - case 0xF8: // Timing clock (sent 24 times per quarter note, only when playing) - case 0xFA: // Start - case 0xFB: // Continue - case 0xFE: // Active sensing (sent every 300ms or MIDI connection assumed lost) - break; - case 0xFC: // Stop - AdPlug_LogWrite("CMF: Received Real Time Stop message (0xFC)\n"); - this->bSongEnd = true; - this->iPlayPointer = 0; // for repeat in endless-play mode - break; - case 0xFF: { // System reset, used as meta-events in a MIDI file - uint8_t iEvent = this->data[this->iPlayPointer++]; - switch (iEvent) { - case 0x2F: // end of track - AdPlug_LogWrite("CMF: End-of-track, stopping playback\n"); - this->bSongEnd = true; - this->iPlayPointer = 0; // for repeat in endless-play mode - break; - default: - AdPlug_LogWrite("CMF: Unknown MIDI meta-event 0xFF 0x%02X\n", iEvent); - break; - } - break; - } - default: - AdPlug_LogWrite("CMF: Unknown MIDI system command 0x%02X\n", iCommand); - break; - } - break; - default: - AdPlug_LogWrite("CMF: Unknown MIDI command 0x%02X\n", iCommand); - break; - } - - if (this->iPlayPointer >= this->iSongLen) { - this->bSongEnd = true; - this->iPlayPointer = 0; // for repeat in endless-play mode - } - - // Read in the number of ticks until the next event - this->iDelayRemaining = this->readMIDINumber(); - } - - return !this->bSongEnd; + // This has to be here and not in getrefresh() for some reason. + this->iDelayRemaining = 0; + + // Read in the next event + while (!this->iDelayRemaining) { + uint8_t iCommand = this->data[this->iPlayPointer++]; + if ((iCommand & 0x80) == 0) { + // Running status, use previous command + this->iPlayPointer--; + iCommand = this->iPrevCommand; + } else { + this->iPrevCommand = iCommand; + } + uint8_t iChannel = iCommand & 0x0F; + switch (iCommand & 0xF0) { + case 0x80: { // Note off (two data bytes) + uint8_t iNote = this->data[this->iPlayPointer++]; + uint8_t iVelocity = this->data[this->iPlayPointer++]; // release velocity + this->cmfNoteOff(iChannel, iNote, iVelocity); + break; + } + case 0x90: { // Note on (two data bytes) + uint8_t iNote = this->data[this->iPlayPointer++]; + uint8_t iVelocity = this->data[this->iPlayPointer++]; // attack velocity + if (iVelocity) { + this->cmfNoteOn(iChannel, iNote, iVelocity); + } else { + // This is a note-off instead (velocity == 0) + this->cmfNoteOff(iChannel, iNote, iVelocity); // 64 is the MIDI default note-off velocity + break; + } + break; + } + case 0xA0: { // Polyphonic key pressure (two data bytes) + uint8_t iNote = this->data[this->iPlayPointer++]; + uint8_t iPressure = this->data[this->iPlayPointer++]; + AdPlug_LogWrite("CMF: Key pressure not yet implemented! (wanted ch%d/note %d set to %d)\n", iChannel, iNote, iPressure); + break; + } + case 0xB0: { // Controller (two data bytes) + uint8_t iController = this->data[this->iPlayPointer++]; + uint8_t iValue = this->data[this->iPlayPointer++]; + this->MIDIcontroller(iChannel, iController, iValue); + break; + } + case 0xC0: { // Instrument change (one data byte) + uint8_t iNewInstrument = this->data[this->iPlayPointer++]; + this->chMIDI[iChannel].iPatch = iNewInstrument; + AdPlug_LogWrite("CMF: Remembering MIDI channel %d now uses patch %d\n", iChannel, iNewInstrument); + break; + } + case 0xD0: { // Channel pressure (one data byte) + uint8_t iPressure = this->data[this->iPlayPointer++]; + AdPlug_LogWrite("CMF: Channel pressure not yet implemented! (wanted ch%d set to %d)\n", iChannel, iPressure); + break; + } + case 0xE0: { // Pitch bend (two data bytes) + uint8_t iLSB = this->data[this->iPlayPointer++]; + uint8_t iMSB = this->data[this->iPlayPointer++]; + uint16_t iValue = (iMSB << 7) | iLSB; + // 8192 is middle/off, 0 is -2 semitones, 16384 is +2 semitones + this->chMIDI[iChannel].iPitchbend = iValue; + AdPlug_LogWrite("CMF: Channel %d pitchbent to %d (%+.2f)\n", iChannel + 1, iValue, (float)(iValue - 8192) / 8192); + break; + } + case 0xF0: // System message (arbitrary data bytes) + switch (iCommand) { + case 0xF0: { // Sysex + uint8_t iNextByte; + AdPlug_LogWrite("Sysex message: "); + do { + iNextByte = this->data[this->iPlayPointer++]; + AdPlug_LogWrite("%02X", iNextByte); + } while ((iNextByte & 0x80) == 0); + AdPlug_LogWrite("\n"); + // This will have read in the terminating EOX (0xF7) message too + break; + } + case 0xF1: // MIDI Time Code Quarter Frame + this->iPlayPointer++; // message data (ignored) + break; + case 0xF2: // Song position pointer + this->iPlayPointer++; // message data (ignored) + this->iPlayPointer++; + break; + case 0xF3: // Song select + this->iPlayPointer++; // message data (ignored) + AdPlug_LogWrite("CMF: MIDI Song Select is not implemented.\n"); + break; + case 0xF6: // Tune request + break; + case 0xF7: // End of System Exclusive (EOX) - should never be read, should be absorbed by Sysex handling code + break; + + // These messages are "real time", meaning they can be sent between + // the bytes of other messages - but we're lazy and don't handle these + // here (hopefully they're not necessary in a MIDI file, and even less + // likely to occur in a CMF.) + case 0xF8: // Timing clock (sent 24 times per quarter note, only when playing) + case 0xFA: // Start + case 0xFB: // Continue + case 0xFE: // Active sensing (sent every 300ms or MIDI connection assumed lost) + break; + case 0xFC: // Stop + AdPlug_LogWrite("CMF: Received Real Time Stop message (0xFC)\n"); + this->bSongEnd = true; + this->iPlayPointer = 0; // for repeat in endless-play mode + break; + case 0xFF: { // System reset, used as meta-events in a MIDI file + uint8_t iEvent = this->data[this->iPlayPointer++]; + switch (iEvent) { + case 0x2F: // end of track + AdPlug_LogWrite("CMF: End-of-track, stopping playback\n"); + this->bSongEnd = true; + this->iPlayPointer = 0; // for repeat in endless-play mode + break; + default: + AdPlug_LogWrite("CMF: Unknown MIDI meta-event 0xFF 0x%02X\n", iEvent); + break; + } + break; + } + default: + AdPlug_LogWrite("CMF: Unknown MIDI system command 0x%02X\n", iCommand); + break; + } + break; + default: + AdPlug_LogWrite("CMF: Unknown MIDI command 0x%02X\n", iCommand); + break; + } + + if (this->iPlayPointer >= this->iSongLen) { + this->bSongEnd = true; + this->iPlayPointer = 0; // for repeat in endless-play mode + } + + // Read in the number of ticks until the next event + this->iDelayRemaining = this->readMIDINumber(); + } + + return !this->bSongEnd; } void CcmfPlayer::rewind(int subsong) { this->opl->init(); - // Initialise + // Initialise // Enable use of WaveSel register on OPL3 (even though we're only an OPL2!) // Apparently this enables nine-channel mode? - this->writeOPL(0x01, 0x20); + this->writeOPL(0x01, 0x20); - // Disable OPL3 mode (can be left enabled by a previous non-CMF song) - this->writeOPL(0x05, 0x00); + // Disable OPL3 mode (can be left enabled by a previous non-CMF song) + this->writeOPL(0x05, 0x00); - // Really make sure CSM+SEL are off (again, Creative's player...) - this->writeOPL(0x08, 0x00); + // Really make sure CSM+SEL are off (again, Creative's player...) + this->writeOPL(0x08, 0x00); - // This freq setting is required for the hihat to sound correct at the start - // of funky.cmf, even though it's for an unrelated channel. - // If it's here however, it makes the hihat in Word Rescue's theme.cmf - // sound really bad. - // TODO: How do we figure out whether we need it or not??? - this->writeOPL(BASE_FNUM_L + 8, 514 & 0xFF); - this->writeOPL(BASE_KEYON_FREQ + 8, (1 << 2) | (514 >> 8)); + // This freq setting is required for the hihat to sound correct at the start + // of funky.cmf, even though it's for an unrelated channel. + // If it's here however, it makes the hihat in Word Rescue's theme.cmf + // sound really bad. + // TODO: How do we figure out whether we need it or not??? + this->writeOPL(BASE_FNUM_L + 8, 514 & 0xFF); + this->writeOPL(BASE_KEYON_FREQ + 8, (1 << 2) | (514 >> 8)); - // default freqs? - this->writeOPL(BASE_FNUM_L + 7, 509 & 0xFF); - this->writeOPL(BASE_KEYON_FREQ + 7, (2 << 2) | (509 >> 8)); - this->writeOPL(BASE_FNUM_L + 6, 432 & 0xFF); - this->writeOPL(BASE_KEYON_FREQ + 6, (2 << 2) | (432 >> 8)); + // default freqs? + this->writeOPL(BASE_FNUM_L + 7, 509 & 0xFF); + this->writeOPL(BASE_KEYON_FREQ + 7, (2 << 2) | (509 >> 8)); + this->writeOPL(BASE_FNUM_L + 6, 432 & 0xFF); + this->writeOPL(BASE_KEYON_FREQ + 6, (2 << 2) | (432 >> 8)); - // Amplify AM + VIB depth. Creative's CMF player does this, and there - // doesn't seem to be any way to stop it from doing so - except for the - // non-standard controller 0x63 I added :-) - this->writeOPL(0xBD, 0xC0); + // Amplify AM + VIB depth. Creative's CMF player does this, and there + // doesn't seem to be any way to stop it from doing so - except for the + // non-standard controller 0x63 I added :-) + this->writeOPL(0xBD, 0xC0); - this->bSongEnd = false; - this->iPlayPointer = 0; - this->iPrevCommand = 0; // just in case + this->bSongEnd = false; + this->iPlayPointer = 0; + this->iPrevCommand = 0; // just in case - // Read in the number of ticks until the first event - this->iDelayRemaining = this->readMIDINumber(); + // Read in the number of ticks until the first event + this->iDelayRemaining = this->readMIDINumber(); // Reset song state. This used to be in the constructor, but the XMMS2 // plugin sets the song length before starting playback. AdPlug plays the @@ -403,47 +402,47 @@ void CcmfPlayer::rewind(int subsong) // results in the state variables below matching the end of the song. When // the real OPL synth is activated for playback, it no longer matches the // state variables and the instruments are not set correctly! - for (int i = 0; i < 9; i++) { - this->chOPL[i].iNoteStart = 0; // no note playing atm - this->chOPL[i].iMIDINote = -1; - this->chOPL[i].iMIDIChannel = -1; - this->chOPL[i].iMIDIPatch = -1; - - this->chMIDI[i].iPatch = -2; - this->chMIDI[i].iPitchbend = 8192; - } - for (int i = 9; i < 16; i++) { - this->chMIDI[i].iPatch = -2; - this->chMIDI[i].iPitchbend = 8192; - } - - memset(this->iCurrentRegs, 0, 256); - - return; + for (int i = 0; i < 9; i++) { + this->chOPL[i].iNoteStart = 0; // no note playing atm + this->chOPL[i].iMIDINote = -1; + this->chOPL[i].iMIDIChannel = -1; + this->chOPL[i].iMIDIPatch = -1; + + this->chMIDI[i].iPatch = -2; + this->chMIDI[i].iPitchbend = 8192; + } + for (int i = 9; i < 16; i++) { + this->chMIDI[i].iPatch = -2; + this->chMIDI[i].iPitchbend = 8192; + } + + memset(this->iCurrentRegs, 0, 256); + + return; } // Return value: 1 == 1 second, 2 == 0.5 seconds float CcmfPlayer::getrefresh() { - if (this->iDelayRemaining) { - return (float)this->cmfHeader.iTicksPerSecond / (float)this->iDelayRemaining; - } else { - // Delay-remaining is zero (e.g. start of song) so use a tiny delay - return this->cmfHeader.iTicksPerSecond; // wait for one tick - } + if (this->iDelayRemaining) { + return (float)this->cmfHeader.iTicksPerSecond / (float)this->iDelayRemaining; + } else { + // Delay-remaining is zero (e.g. start of song) so use a tiny delay + return this->cmfHeader.iTicksPerSecond; // wait for one tick + } } std::string CcmfPlayer::gettitle() { - return this->strTitle; + return this->strTitle; } std::string CcmfPlayer::getauthor() { - return this->strComposer; + return this->strComposer; } std::string CcmfPlayer::getdesc() { - return this->strRemarks; + return this->strRemarks; } @@ -454,14 +453,14 @@ std::string CcmfPlayer::getdesc() // Read a variable-length integer from MIDI data uint32_t CcmfPlayer::readMIDINumber() { - uint32_t iValue = 0; - for (int i = 0; i < 4; i++) { - uint8_t iNext = this->data[this->iPlayPointer++]; - iValue <<= 7; - iValue |= (iNext & 0x7F); // ignore the MSB - if ((iNext & 0x80) == 0) break; // last byte has the MSB unset - } - return iValue; + uint32_t iValue = 0; + for (int i = 0; i < 4; i++) { + uint8_t iNext = this->data[this->iPlayPointer++]; + iValue <<= 7; + iValue |= (iNext & 0x7F); // ignore the MSB + if ((iNext & 0x80) == 0) break; // last byte has the MSB unset + } + return iValue; } // iChannel: OPL channel (0-8) @@ -471,318 +470,318 @@ uint32_t CcmfPlayer::readMIDINumber() // iInstrument: Index into this->pInstruments array of CMF instruments void CcmfPlayer::writeInstrumentSettings(uint8_t iChannel, uint8_t iOperatorSource, uint8_t iOperatorDest, uint8_t iInstrument) { - assert(iChannel <= 8); + assert(iChannel <= 8); - uint8_t iOPLOffset = OPLOFFSET(iChannel); - if (iOperatorDest) iOPLOffset += 3; // Carrier if iOperator == 1 (else Modulator) + uint8_t iOPLOffset = OPLOFFSET(iChannel); + if (iOperatorDest) iOPLOffset += 3; // Carrier if iOperator == 1 (else Modulator) - this->writeOPL(BASE_CHAR_MULT + iOPLOffset, this->pInstruments[iInstrument].op[iOperatorSource].iCharMult); - this->writeOPL(BASE_SCAL_LEVL + iOPLOffset, this->pInstruments[iInstrument].op[iOperatorSource].iScalingOutput); - this->writeOPL(BASE_ATCK_DCAY + iOPLOffset, this->pInstruments[iInstrument].op[iOperatorSource].iAttackDecay); - this->writeOPL(BASE_SUST_RLSE + iOPLOffset, this->pInstruments[iInstrument].op[iOperatorSource].iSustainRelease); - this->writeOPL(BASE_WAVE + iOPLOffset, this->pInstruments[iInstrument].op[iOperatorSource].iWaveSel); + this->writeOPL(BASE_CHAR_MULT + iOPLOffset, this->pInstruments[iInstrument].op[iOperatorSource].iCharMult); + this->writeOPL(BASE_SCAL_LEVL + iOPLOffset, this->pInstruments[iInstrument].op[iOperatorSource].iScalingOutput); + this->writeOPL(BASE_ATCK_DCAY + iOPLOffset, this->pInstruments[iInstrument].op[iOperatorSource].iAttackDecay); + this->writeOPL(BASE_SUST_RLSE + iOPLOffset, this->pInstruments[iInstrument].op[iOperatorSource].iSustainRelease); + this->writeOPL(BASE_WAVE + iOPLOffset, this->pInstruments[iInstrument].op[iOperatorSource].iWaveSel); - // TODO: Check to see whether we should only be loading this for one or both operators - this->writeOPL(BASE_FEED_CONN + iChannel, this->pInstruments[iInstrument].iConnection); - return; + // TODO: Check to see whether we should only be loading this for one or both operators + this->writeOPL(BASE_FEED_CONN + iChannel, this->pInstruments[iInstrument].iConnection); + return; } // Write a byte to the OPL "chip" and update the current record of register states void CcmfPlayer::writeOPL(uint8_t iRegister, uint8_t iValue) { - this->opl->write(iRegister, iValue); - this->iCurrentRegs[iRegister] = iValue; - return; + this->opl->write(iRegister, iValue); + this->iCurrentRegs[iRegister] = iValue; + return; } void CcmfPlayer::cmfNoteOn(uint8_t iChannel, uint8_t iNote, uint8_t iVelocity) { - uint8_t iBlock = iNote / 12; - if (iBlock > 1) iBlock--; // keep in the same range as the Creative player - //if (iBlock > 7) iBlock = 7; // don't want to go out of range - - double d = pow(2, ( - (double)iNote + ( - (this->chMIDI[iChannel].iPitchbend - 8192) / 8192.0 - ) + ( - this->iTranspose / 128 - ) - 9) / 12.0 - (iBlock - 20)) - * 440.0 / 32.0 / 50000.0; - uint16_t iOPLFNum = (uint16_t)(d+0.5); - if (iOPLFNum > 1023) AdPlug_LogWrite("CMF: This note is out of range! (send this song to malvineous@shikadi.net!)\n"); - - // See if we're playing a rhythm mode percussive instrument - if ((iChannel > 10) && (this->bPercussive)) { - uint8_t iPercChannel = this->getPercChannel(iChannel); - - // Will have to set every time (easier) than figuring out whether the mod - // or car needs to be changed. - //if (this->chOPL[iPercChannel].iMIDIPatch != this->chMIDI[iChannel].iPatch) { - this->MIDIchangeInstrument(iPercChannel, iChannel, this->chMIDI[iChannel].iPatch); - //} - - /* Velocity calculations - TODO: Work out the proper formula - - iVelocity -> iLevel (values generated by Creative's player) - 7f -> 00 - 7c -> 00 - - 7b -> 09 - 73 -> 0a - 6b -> 0b - 63 -> 0c - 5b -> 0d - 53 -> 0e - 4b -> 0f - 43 -> 10 - 3b -> 11 - 33 -> 13 - 2b -> 15 - 23 -> 19 - 1b -> 1b - 13 -> 1d - 0b -> 1f - 03 -> 21 - - 02 -> 21 - 00 -> N/A (note off) - */ - // Approximate formula, need to figure out more accurate one (my maths isn't so good...) - int iLevel = 0x25 - (int) sqrt(iVelocity * 16 /* 6 */); // (127 - iVelocity) * 0x20 / 127; - if (iVelocity > 0x7b) iLevel = 0; // full volume - if (iLevel < 0) iLevel = 0; - if (iLevel > 0x3F) iLevel = 0x3F; - //if (iVelocity < 0x40) iLevel = 0x10; - - int iOPLOffset = BASE_SCAL_LEVL + OPLOFFSET(iPercChannel); - //if ((iChannel == 11) || (iChannel == 12) || (iChannel == 14)) { - if (iChannel == 11) iOPLOffset += 3; // only do bassdrum carrier for volume control - //iOPLOffset += 3; // carrier - this->writeOPL(iOPLOffset, (this->iCurrentRegs[iOPLOffset] & ~0x3F) | iLevel);//(iVelocity * 0x3F / 127)); - //} - // Bass drum (ch11) uses both operators - //if (iChannel == 11) this->writeOPL(iOPLOffset + 3, (this->iCurrentRegs[iOPLOffset + 3] & ~0x3F) | iLevel); - -/* #ifdef USE_VELOCITY // Official CMF player seems to ignore velocity levels - uint16_t iLevel = 0x2F - (iVelocity * 0x2F / 127); // 0x2F should be 0x3F but it's too quiet then - AdPlug_LogWrite("%02X + vel %d (lev %02X) == %02X\n", this->iCurrentRegs[iOPLOffset], iVelocity, iLevel, (this->iCurrentRegs[iOPLOffset] & ~0x3F) | iLevel); - //this->writeOPL(iOPLOffset, (this->iCurrentRegs[iOPLOffset] & ~0x3F) | (0x3F - (iVelocity >> 1)));//(iVelocity * 0x3F / 127)); - this->writeOPL(iOPLOffset, (this->iCurrentRegs[iOPLOffset] & ~0x3F) | iLevel);//(iVelocity * 0x3F / 127)); - #endif*/ - - // Apparently you can't set the frequency for the cymbal or hihat? - // Vinyl requires you don't set it, Kiloblaster requires you do! - this->writeOPL(BASE_FNUM_L + iPercChannel, iOPLFNum & 0xFF); - this->writeOPL(BASE_KEYON_FREQ + iPercChannel, (iBlock << 2) | ((iOPLFNum >> 8) & 0x03)); - - uint8_t iBit = 1 << (15 - iChannel); - - // Turn the perc instrument off if it's already playing (OPL can't do - // polyphonic notes w/ percussion) - if (this->iCurrentRegs[BASE_RHYTHM] & iBit) this->writeOPL(BASE_RHYTHM, this->iCurrentRegs[BASE_RHYTHM] & ~iBit); - - // I wonder whether we need to delay or anything here? - - // Turn the note on - //if (iChannel == 15) { - this->writeOPL(BASE_RHYTHM, this->iCurrentRegs[BASE_RHYTHM] | iBit); - //AdPlug_LogWrite("CMF: Note %d on MIDI channel %d (mapped to OPL channel %d-1) - vel %02X, fnum %d/%d\n", iNote, iChannel, iPercChannel+1, iVelocity, iOPLFNum, iBlock); - //} - - this->chOPL[iPercChannel].iNoteStart = ++this->iNoteCount; - this->chOPL[iPercChannel].iMIDIChannel = iChannel; - this->chOPL[iPercChannel].iMIDINote = iNote; - - } else { // Non rhythm-mode or a normal instrument channel - - // Figure out which OPL channel to play this note on - int iOPLChannel = -1; - int iNumChannels = this->bPercussive ? 6 : 9; - for (int i = iNumChannels - 1; i >= 0; i--) { - // If there's no note playing on this OPL channel, use that - if (this->chOPL[i].iNoteStart == 0) { - iOPLChannel = i; - // See if this channel is already set to the instrument we want. - if (this->chOPL[i].iMIDIPatch == this->chMIDI[iChannel].iPatch) { - // It is, so stop searching - break; - } // else keep searching just in case there's a better match - } - } - if (iOPLChannel == -1) { - // All channels were in use, find the one with the longest note - iOPLChannel = 0; - int iEarliest = this->chOPL[0].iNoteStart; - for (int i = 1; i < iNumChannels; i++) { - if (this->chOPL[i].iNoteStart < iEarliest) { - // Found a channel with a note being played for longer - iOPLChannel = i; - iEarliest = this->chOPL[i].iNoteStart; - } - } - AdPlug_LogWrite("CMF: Too many polyphonic notes, cutting note on channel %d\n", iOPLChannel); - } - - // Run through all the channels with negative notestart values - these - // channels have had notes recently stop - and increment the counter - // to slowly move the channel closer to being reused for a future note. - //for (int i = 0; i < iNumChannels; i++) { - // if (this->chOPL[i].iNoteStart < 0) this->chOPL[i].iNoteStart++; - //} - - // Now the new note should be played on iOPLChannel, but see if the instrument - // is right first. - if (this->chOPL[iOPLChannel].iMIDIPatch != this->chMIDI[iChannel].iPatch) { - this->MIDIchangeInstrument(iOPLChannel, iChannel, this->chMIDI[iChannel].iPatch); - } - - this->chOPL[iOPLChannel].iNoteStart = ++this->iNoteCount; - this->chOPL[iOPLChannel].iMIDIChannel = iChannel; - this->chOPL[iOPLChannel].iMIDINote = iNote; - - #ifdef USE_VELOCITY // Official CMF player seems to ignore velocity levels - // Adjust the channel volume to match the note velocity - uint8_t iOPLOffset = BASE_SCAL_LEVL + OPLOFFSET(iChannel) + 3; // +3 == Carrier - uint16_t iLevel = 0x2F - (iVelocity * 0x2F / 127); // 0x2F should be 0x3F but it's too quiet then - this->writeOPL(iOPLOffset, (this->iCurrentRegs[iOPLOffset] & ~0x3F) | iLevel); - #endif - - // Set the frequency and play the note - this->writeOPL(BASE_FNUM_L + iOPLChannel, iOPLFNum & 0xFF); - this->writeOPL(BASE_KEYON_FREQ + iOPLChannel, OPLBIT_KEYON | (iBlock << 2) | ((iOPLFNum & 0x300) >> 8)); - } - return; + uint8_t iBlock = iNote / 12; + if (iBlock > 1) iBlock--; // keep in the same range as the Creative player + //if (iBlock > 7) iBlock = 7; // don't want to go out of range + + double d = pow(2, ( + (double)iNote + ( + (this->chMIDI[iChannel].iPitchbend - 8192) / 8192.0 + ) + ( + this->iTranspose / 128 + ) - 9) / 12.0 - (iBlock - 20)) + * 440.0 / 32.0 / 50000.0; + uint16_t iOPLFNum = (uint16_t)(d+0.5); + if (iOPLFNum > 1023) AdPlug_LogWrite("CMF: This note is out of range! (send this song to malvineous@shikadi.net!)\n"); + + // See if we're playing a rhythm mode percussive instrument + if ((iChannel > 10) && (this->bPercussive)) { + uint8_t iPercChannel = this->getPercChannel(iChannel); + + // Will have to set every time (easier) than figuring out whether the mod + // or car needs to be changed. + //if (this->chOPL[iPercChannel].iMIDIPatch != this->chMIDI[iChannel].iPatch) { + this->MIDIchangeInstrument(iPercChannel, iChannel, this->chMIDI[iChannel].iPatch); + //} + + /* Velocity calculations - TODO: Work out the proper formula + + iVelocity -> iLevel (values generated by Creative's player) + 7f -> 00 + 7c -> 00 + + 7b -> 09 + 73 -> 0a + 6b -> 0b + 63 -> 0c + 5b -> 0d + 53 -> 0e + 4b -> 0f + 43 -> 10 + 3b -> 11 + 33 -> 13 + 2b -> 15 + 23 -> 19 + 1b -> 1b + 13 -> 1d + 0b -> 1f + 03 -> 21 + + 02 -> 21 + 00 -> N/A (note off) + */ + // Approximate formula, need to figure out more accurate one (my maths isn't so good...) + int iLevel = 0x25 - sqrt(iVelocity * 16/*6*/);//(127 - iVelocity) * 0x20 / 127; + if (iVelocity > 0x7b) iLevel = 0; // full volume + if (iLevel < 0) iLevel = 0; + if (iLevel > 0x3F) iLevel = 0x3F; + //if (iVelocity < 0x40) iLevel = 0x10; + + int iOPLOffset = BASE_SCAL_LEVL + OPLOFFSET(iPercChannel); + //if ((iChannel == 11) || (iChannel == 12) || (iChannel == 14)) { + if (iChannel == 11) iOPLOffset += 3; // only do bassdrum carrier for volume control + //iOPLOffset += 3; // carrier + this->writeOPL(iOPLOffset, (this->iCurrentRegs[iOPLOffset] & ~0x3F) | iLevel);//(iVelocity * 0x3F / 127)); + //} + // Bass drum (ch11) uses both operators + //if (iChannel == 11) this->writeOPL(iOPLOffset + 3, (this->iCurrentRegs[iOPLOffset + 3] & ~0x3F) | iLevel); + +/* #ifdef USE_VELOCITY // Official CMF player seems to ignore velocity levels + uint16_t iLevel = 0x2F - (iVelocity * 0x2F / 127); // 0x2F should be 0x3F but it's too quiet then + AdPlug_LogWrite("%02X + vel %d (lev %02X) == %02X\n", this->iCurrentRegs[iOPLOffset], iVelocity, iLevel, (this->iCurrentRegs[iOPLOffset] & ~0x3F) | iLevel); + //this->writeOPL(iOPLOffset, (this->iCurrentRegs[iOPLOffset] & ~0x3F) | (0x3F - (iVelocity >> 1)));//(iVelocity * 0x3F / 127)); + this->writeOPL(iOPLOffset, (this->iCurrentRegs[iOPLOffset] & ~0x3F) | iLevel);//(iVelocity * 0x3F / 127)); + #endif*/ + + // Apparently you can't set the frequency for the cymbal or hihat? + // Vinyl requires you don't set it, Kiloblaster requires you do! + this->writeOPL(BASE_FNUM_L + iPercChannel, iOPLFNum & 0xFF); + this->writeOPL(BASE_KEYON_FREQ + iPercChannel, (iBlock << 2) | ((iOPLFNum >> 8) & 0x03)); + + uint8_t iBit = 1 << (15 - iChannel); + + // Turn the perc instrument off if it's already playing (OPL can't do + // polyphonic notes w/ percussion) + if (this->iCurrentRegs[BASE_RHYTHM] & iBit) this->writeOPL(BASE_RHYTHM, this->iCurrentRegs[BASE_RHYTHM] & ~iBit); + + // I wonder whether we need to delay or anything here? + + // Turn the note on + //if (iChannel == 15) { + this->writeOPL(BASE_RHYTHM, this->iCurrentRegs[BASE_RHYTHM] | iBit); + //AdPlug_LogWrite("CMF: Note %d on MIDI channel %d (mapped to OPL channel %d-1) - vel %02X, fnum %d/%d\n", iNote, iChannel, iPercChannel+1, iVelocity, iOPLFNum, iBlock); + //} + + this->chOPL[iPercChannel].iNoteStart = ++this->iNoteCount; + this->chOPL[iPercChannel].iMIDIChannel = iChannel; + this->chOPL[iPercChannel].iMIDINote = iNote; + + } else { // Non rhythm-mode or a normal instrument channel + + // Figure out which OPL channel to play this note on + int iOPLChannel = -1; + int iNumChannels = this->bPercussive ? 6 : 9; + for (int i = iNumChannels - 1; i >= 0; i--) { + // If there's no note playing on this OPL channel, use that + if (this->chOPL[i].iNoteStart == 0) { + iOPLChannel = i; + // See if this channel is already set to the instrument we want. + if (this->chOPL[i].iMIDIPatch == this->chMIDI[iChannel].iPatch) { + // It is, so stop searching + break; + } // else keep searching just in case there's a better match + } + } + if (iOPLChannel == -1) { + // All channels were in use, find the one with the longest note + iOPLChannel = 0; + int iEarliest = this->chOPL[0].iNoteStart; + for (int i = 1; i < iNumChannels; i++) { + if (this->chOPL[i].iNoteStart < iEarliest) { + // Found a channel with a note being played for longer + iOPLChannel = i; + iEarliest = this->chOPL[i].iNoteStart; + } + } + AdPlug_LogWrite("CMF: Too many polyphonic notes, cutting note on channel %d\n", iOPLChannel); + } + + // Run through all the channels with negative notestart values - these + // channels have had notes recently stop - and increment the counter + // to slowly move the channel closer to being reused for a future note. + //for (int i = 0; i < iNumChannels; i++) { + // if (this->chOPL[i].iNoteStart < 0) this->chOPL[i].iNoteStart++; + //} + + // Now the new note should be played on iOPLChannel, but see if the instrument + // is right first. + if (this->chOPL[iOPLChannel].iMIDIPatch != this->chMIDI[iChannel].iPatch) { + this->MIDIchangeInstrument(iOPLChannel, iChannel, this->chMIDI[iChannel].iPatch); + } + + this->chOPL[iOPLChannel].iNoteStart = ++this->iNoteCount; + this->chOPL[iOPLChannel].iMIDIChannel = iChannel; + this->chOPL[iOPLChannel].iMIDINote = iNote; + + #ifdef USE_VELOCITY // Official CMF player seems to ignore velocity levels + // Adjust the channel volume to match the note velocity + uint8_t iOPLOffset = BASE_SCAL_LEVL + OPLOFFSET(iChannel) + 3; // +3 == Carrier + uint16_t iLevel = 0x2F - (iVelocity * 0x2F / 127); // 0x2F should be 0x3F but it's too quiet then + this->writeOPL(iOPLOffset, (this->iCurrentRegs[iOPLOffset] & ~0x3F) | iLevel); + #endif + + // Set the frequency and play the note + this->writeOPL(BASE_FNUM_L + iOPLChannel, iOPLFNum & 0xFF); + this->writeOPL(BASE_KEYON_FREQ + iOPLChannel, OPLBIT_KEYON | (iBlock << 2) | ((iOPLFNum & 0x300) >> 8)); + } + return; } void CcmfPlayer::cmfNoteOff(uint8_t iChannel, uint8_t iNote, uint8_t iVelocity) { - if ((iChannel > 10) && (this->bPercussive)) { - int iOPLChannel = this->getPercChannel(iChannel); - if (this->chOPL[iOPLChannel].iMIDINote != iNote) return; // there's a different note playing now - this->writeOPL(BASE_RHYTHM, this->iCurrentRegs[BASE_RHYTHM] & ~(1 << (15 - iChannel))); - this->chOPL[iOPLChannel].iNoteStart = 0; // channel free - } else { // Non rhythm-mode or a normal instrument channel - int iOPLChannel = -1; - int iNumChannels = this->bPercussive ? 6 : 9; - for (int i = 0; i < iNumChannels; i++) { - if ( - (this->chOPL[i].iMIDIChannel == iChannel) && - (this->chOPL[i].iMIDINote == iNote) && - (this->chOPL[i].iNoteStart != 0) - ) { - // Found the note, switch it off - this->chOPL[i].iNoteStart = 0; - iOPLChannel = i; - break; - } - } - if (iOPLChannel == -1) return; - - this->writeOPL(BASE_KEYON_FREQ + iOPLChannel, this->iCurrentRegs[BASE_KEYON_FREQ + iOPLChannel] & ~OPLBIT_KEYON); - } - return; + if ((iChannel > 10) && (this->bPercussive)) { + int iOPLChannel = this->getPercChannel(iChannel); + if (this->chOPL[iOPLChannel].iMIDINote != iNote) return; // there's a different note playing now + this->writeOPL(BASE_RHYTHM, this->iCurrentRegs[BASE_RHYTHM] & ~(1 << (15 - iChannel))); + this->chOPL[iOPLChannel].iNoteStart = 0; // channel free + } else { // Non rhythm-mode or a normal instrument channel + int iOPLChannel = -1; + int iNumChannels = this->bPercussive ? 6 : 9; + for (int i = 0; i < iNumChannels; i++) { + if ( + (this->chOPL[i].iMIDIChannel == iChannel) && + (this->chOPL[i].iMIDINote == iNote) && + (this->chOPL[i].iNoteStart != 0) + ) { + // Found the note, switch it off + this->chOPL[i].iNoteStart = 0; + iOPLChannel = i; + break; + } + } + if (iOPLChannel == -1) return; + + this->writeOPL(BASE_KEYON_FREQ + iOPLChannel, this->iCurrentRegs[BASE_KEYON_FREQ + iOPLChannel] & ~OPLBIT_KEYON); + } + return; } uint8_t CcmfPlayer::getPercChannel(uint8_t iChannel) { - switch (iChannel) { - case 11: return 7-1; // Bass drum - case 12: return 8-1; // Snare drum - case 13: return 9-1; // Tom tom - case 14: return 9-1; // Top cymbal - case 15: return 8-1; // Hihat - } - AdPlug_LogWrite("CMF ERR: Tried to get the percussion channel from MIDI channel %d - this shouldn't happen!\n", iChannel); - return 0; + switch (iChannel) { + case 11: return 7-1; // Bass drum + case 12: return 8-1; // Snare drum + case 13: return 9-1; // Tom tom + case 14: return 9-1; // Top cymbal + case 15: return 8-1; // Hihat + } + AdPlug_LogWrite("CMF ERR: Tried to get the percussion channel from MIDI channel %d - this shouldn't happen!\n", iChannel); + return 0; } void CcmfPlayer::MIDIchangeInstrument(uint8_t iOPLChannel, uint8_t iMIDIChannel, uint8_t iNewInstrument) { - if ((iMIDIChannel > 10) && (this->bPercussive)) { - switch (iMIDIChannel) { - case 11: // Bass drum (operator 13+16 == channel 7 modulator+carrier) - this->writeInstrumentSettings(7-1, 0, 0, iNewInstrument); - this->writeInstrumentSettings(7-1, 1, 1, iNewInstrument); - break; - case 12: // Snare drum (operator 17 == channel 8 carrier) - //case 15: - this->writeInstrumentSettings(8-1, 0, 1, iNewInstrument); - - // - //this->writeInstrumentSettings(8-1, 0, 0, iNewInstrument); - break; - case 13: // Tom tom (operator 15 == channel 9 modulator) - //case 14: - this->writeInstrumentSettings(9-1, 0, 0, iNewInstrument); - - // - //this->writeInstrumentSettings(9-1, 0, 1, iNewInstrument); - break; - case 14: // Top cymbal (operator 18 == channel 9 carrier) - this->writeInstrumentSettings(9-1, 0, 1, iNewInstrument); - break; - case 15: // Hi-hat (operator 14 == channel 8 modulator) - this->writeInstrumentSettings(8-1, 0, 0, iNewInstrument); - break; - default: - AdPlug_LogWrite("CMF: Invalid MIDI channel %d (not melodic and not percussive!)\n", iMIDIChannel + 1); - break; - } - this->chOPL[iOPLChannel].iMIDIPatch = iNewInstrument; - } else { - // Standard nine OPL channels - this->writeInstrumentSettings(iOPLChannel, 0, 0, iNewInstrument); - this->writeInstrumentSettings(iOPLChannel, 1, 1, iNewInstrument); - this->chOPL[iOPLChannel].iMIDIPatch = iNewInstrument; - } - return; + if ((iMIDIChannel > 10) && (this->bPercussive)) { + switch (iMIDIChannel) { + case 11: // Bass drum (operator 13+16 == channel 7 modulator+carrier) + this->writeInstrumentSettings(7-1, 0, 0, iNewInstrument); + this->writeInstrumentSettings(7-1, 1, 1, iNewInstrument); + break; + case 12: // Snare drum (operator 17 == channel 8 carrier) + //case 15: + this->writeInstrumentSettings(8-1, 0, 1, iNewInstrument); + + // + //this->writeInstrumentSettings(8-1, 0, 0, iNewInstrument); + break; + case 13: // Tom tom (operator 15 == channel 9 modulator) + //case 14: + this->writeInstrumentSettings(9-1, 0, 0, iNewInstrument); + + // + //this->writeInstrumentSettings(9-1, 0, 1, iNewInstrument); + break; + case 14: // Top cymbal (operator 18 == channel 9 carrier) + this->writeInstrumentSettings(9-1, 0, 1, iNewInstrument); + break; + case 15: // Hi-hat (operator 14 == channel 8 modulator) + this->writeInstrumentSettings(8-1, 0, 0, iNewInstrument); + break; + default: + AdPlug_LogWrite("CMF: Invalid MIDI channel %d (not melodic and not percussive!)\n", iMIDIChannel + 1); + break; + } + this->chOPL[iOPLChannel].iMIDIPatch = iNewInstrument; + } else { + // Standard nine OPL channels + this->writeInstrumentSettings(iOPLChannel, 0, 0, iNewInstrument); + this->writeInstrumentSettings(iOPLChannel, 1, 1, iNewInstrument); + this->chOPL[iOPLChannel].iMIDIPatch = iNewInstrument; + } + return; } void CcmfPlayer::MIDIcontroller(uint8_t iChannel, uint8_t iController, uint8_t iValue) { - switch (iController) { - case 0x63: - // Custom extension to allow CMF files to switch the AM+VIB depth on and - // off (officially both are on, and there's no way to switch them off.) - // Controller values: - // 0 == AM+VIB off - // 1 == VIB on - // 2 == AM on - // 3 == AM+VIB on - if (iValue) { - this->writeOPL(BASE_RHYTHM, (this->iCurrentRegs[BASE_RHYTHM] & ~0xC0) | (iValue << 6)); // switch AM+VIB extension on - } else { - this->writeOPL(BASE_RHYTHM, this->iCurrentRegs[BASE_RHYTHM] & ~0xC0); // switch AM+VIB extension off - } - AdPlug_LogWrite("CMF: AM+VIB depth change - AM %s, VIB %s\n", - (this->iCurrentRegs[BASE_RHYTHM] & 0x80) ? "on" : "off", - (this->iCurrentRegs[BASE_RHYTHM] & 0x40) ? "on" : "off"); - break; - case 0x66: - AdPlug_LogWrite("CMF: Song set marker to 0x%02X\n", iValue); - break; - case 0x67: - this->bPercussive = (iValue != 0); - if (this->bPercussive) { - this->writeOPL(BASE_RHYTHM, this->iCurrentRegs[BASE_RHYTHM] | 0x20); // switch rhythm-mode on - } else { - this->writeOPL(BASE_RHYTHM, this->iCurrentRegs[BASE_RHYTHM] & ~0x20); // switch rhythm-mode off - } - AdPlug_LogWrite("CMF: Percussive/rhythm mode %s\n", this->bPercussive ? "enabled" : "disabled"); - break; - case 0x68: - // TODO: Shouldn't this just affect the one channel, not the whole song? -- have pitchbends for that - this->iTranspose = iValue; - AdPlug_LogWrite("CMF: Transposing all notes up by %d * 1/128ths of a semitone.\n", iValue); - break; - case 0x69: - this->iTranspose = -iValue; - AdPlug_LogWrite("CMF: Transposing all notes down by %d * 1/128ths of a semitone.\n", iValue); - break; - default: - AdPlug_LogWrite("CMF: Unsupported MIDI controller 0x%02X, ignoring.\n", iController); - break; - } - return; + switch (iController) { + case 0x63: + // Custom extension to allow CMF files to switch the AM+VIB depth on and + // off (officially both are on, and there's no way to switch them off.) + // Controller values: + // 0 == AM+VIB off + // 1 == VIB on + // 2 == AM on + // 3 == AM+VIB on + if (iValue) { + this->writeOPL(BASE_RHYTHM, (this->iCurrentRegs[BASE_RHYTHM] & ~0xC0) | (iValue << 6)); // switch AM+VIB extension on + } else { + this->writeOPL(BASE_RHYTHM, this->iCurrentRegs[BASE_RHYTHM] & ~0xC0); // switch AM+VIB extension off + } + AdPlug_LogWrite("CMF: AM+VIB depth change - AM %s, VIB %s\n", + (this->iCurrentRegs[BASE_RHYTHM] & 0x80) ? "on" : "off", + (this->iCurrentRegs[BASE_RHYTHM] & 0x40) ? "on" : "off"); + break; + case 0x66: + AdPlug_LogWrite("CMF: Song set marker to 0x%02X\n", iValue); + break; + case 0x67: + this->bPercussive = (iValue != 0); + if (this->bPercussive) { + this->writeOPL(BASE_RHYTHM, this->iCurrentRegs[BASE_RHYTHM] | 0x20); // switch rhythm-mode on + } else { + this->writeOPL(BASE_RHYTHM, this->iCurrentRegs[BASE_RHYTHM] & ~0x20); // switch rhythm-mode off + } + AdPlug_LogWrite("CMF: Percussive/rhythm mode %s\n", this->bPercussive ? "enabled" : "disabled"); + break; + case 0x68: + // TODO: Shouldn't this just affect the one channel, not the whole song? -- have pitchbends for that + this->iTranspose = iValue; + AdPlug_LogWrite("CMF: Transposing all notes up by %d * 1/128ths of a semitone.\n", iValue); + break; + case 0x69: + this->iTranspose = -iValue; + AdPlug_LogWrite("CMF: Transposing all notes down by %d * 1/128ths of a semitone.\n", iValue); + break; + default: + AdPlug_LogWrite("CMF: Unsupported MIDI controller 0x%02X, ignoring.\n", iController); + break; + } + return; } diff --git a/src/adplug/core/cmf.h b/src/adplug/core/cmf.h index 3e9bb0a..27ed96e 100644 --- a/src/adplug/core/cmf.h +++ b/src/adplug/core/cmf.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2009 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -23,90 +23,90 @@ #include "player.h" typedef struct { - uint16_t iInstrumentBlockOffset; - uint16_t iMusicOffset; - uint16_t iTicksPerQuarterNote; - uint16_t iTicksPerSecond; - uint16_t iTagOffsetTitle; - uint16_t iTagOffsetComposer; - uint16_t iTagOffsetRemarks; - uint8_t iChannelsInUse[16]; - uint16_t iNumInstruments; - uint16_t iTempo; + uint16_t iInstrumentBlockOffset; + uint16_t iMusicOffset; + uint16_t iTicksPerQuarterNote; + uint16_t iTicksPerSecond; + uint16_t iTagOffsetTitle; + uint16_t iTagOffsetComposer; + uint16_t iTagOffsetRemarks; + uint8_t iChannelsInUse[16]; + uint16_t iNumInstruments; + uint16_t iTempo; } CMFHEADER; typedef struct { - uint8_t iCharMult; - uint8_t iScalingOutput; - uint8_t iAttackDecay; - uint8_t iSustainRelease; - uint8_t iWaveSel; + uint8_t iCharMult; + uint8_t iScalingOutput; + uint8_t iAttackDecay; + uint8_t iSustainRelease; + uint8_t iWaveSel; } OPERATOR; typedef struct { - OPERATOR op[2]; // 0 == modulator, 1 == carrier - uint8_t iConnection; + OPERATOR op[2]; // 0 == modulator, 1 == carrier + uint8_t iConnection; } SBI; typedef struct { - int iPatch; // MIDI patch for this channel - int iPitchbend; // Current pitchbend amount for this channel + int iPatch; // MIDI patch for this channel + int iPitchbend; // Current pitchbend amount for this channel } MIDICHANNEL; typedef struct { - int iNoteStart; // When the note started playing (longest notes get cut first, 0 == channel free) - int iMIDINote; // MIDI note number currently being played on this OPL channel - int iMIDIChannel; // Source MIDI channel where this note came from - int iMIDIPatch; // Current MIDI patch set on this OPL channel + int iNoteStart; // When the note started playing (longest notes get cut first, 0 == channel free) + int iMIDINote; // MIDI note number currently being played on this OPL channel + int iMIDIChannel; // Source MIDI channel where this note came from + int iMIDIPatch; // Current MIDI patch set on this OPL channel } OPLCHANNEL; class CcmfPlayer: public CPlayer { - private: - uint8_t *data; // song data (CMF music block) - int iPlayPointer; // Current location of playback pointer - int iSongLen; // Max value for iPlayPointer - CMFHEADER cmfHeader; - SBI *pInstruments; - bool bPercussive; // are rhythm-mode instruments enabled? - uint8_t iCurrentRegs[256]; // Current values in the OPL chip - int iTranspose; // Transpose amount for entire song (between -128 and +128) - uint8_t iPrevCommand; // Previous command (used for repeated MIDI commands, as the seek and playback code need to share this) + private: + uint8_t *data; // song data (CMF music block) + int iPlayPointer; // Current location of playback pointer + int iSongLen; // Max value for iPlayPointer + CMFHEADER cmfHeader; + SBI *pInstruments; + bool bPercussive; // are rhythm-mode instruments enabled? + uint8_t iCurrentRegs[256]; // Current values in the OPL chip + int iTranspose; // Transpose amount for entire song (between -128 and +128) + uint8_t iPrevCommand; // Previous command (used for repeated MIDI commands, as the seek and playback code need to share this) - int iNoteCount; // Used to count how long notes have been playing for - MIDICHANNEL chMIDI[16]; - OPLCHANNEL chOPL[9]; + int iNoteCount; // Used to count how long notes have been playing for + MIDICHANNEL chMIDI[16]; + OPLCHANNEL chOPL[9]; - // Additions for AdPlug's design - int iDelayRemaining; - bool bSongEnd; - std::string strTitle, strComposer, strRemarks; + // Additions for AdPlug's design + int iDelayRemaining; + bool bSongEnd; + std::string strTitle, strComposer, strRemarks; - public: - static CPlayer *factory(Copl *newopl); + public: + static CPlayer *factory(Copl *newopl); - CcmfPlayer(Copl *newopl); - ~CcmfPlayer(); + CcmfPlayer(Copl *newopl); + ~CcmfPlayer(); - bool load(VFSFile &fd, const CFileProvider &fp); - bool update(); - void rewind(int subsong); - float getrefresh(); + bool load(const std::string &filename, const CFileProvider &fp); + bool update(); + void rewind(int subsong); + float getrefresh(); - std::string gettype() - { return std::string("Creative Music File (CMF)"); }; - std::string gettitle(); - std::string getauthor(); - std::string getdesc(); + std::string gettype() + { return std::string("Creative Music File (CMF)"); }; + std::string gettitle(); + std::string getauthor(); + std::string getdesc(); - protected: - uint32_t readMIDINumber(); - void writeInstrumentSettings(uint8_t iChannel, uint8_t iOperatorSource, uint8_t iOperatorDest, uint8_t iInstrument); - void writeOPL(uint8_t iRegister, uint8_t iValue); - void cmfNoteOn(uint8_t iChannel, uint8_t iNote, uint8_t iVelocity); - void cmfNoteOff(uint8_t iChannel, uint8_t iNote, uint8_t iVelocity); - uint8_t getPercChannel(uint8_t iChannel); - void MIDIchangeInstrument(uint8_t iOPLChannel, uint8_t iMIDIChannel, uint8_t iNewInstrument); - void MIDIcontroller(uint8_t iChannel, uint8_t iController, uint8_t iValue); + protected: + uint32_t readMIDINumber(); + void writeInstrumentSettings(uint8_t iChannel, uint8_t iOperatorSource, uint8_t iOperatorDest, uint8_t iInstrument); + void writeOPL(uint8_t iRegister, uint8_t iValue); + void cmfNoteOn(uint8_t iChannel, uint8_t iNote, uint8_t iVelocity); + void cmfNoteOff(uint8_t iChannel, uint8_t iNote, uint8_t iVelocity); + uint8_t getPercChannel(uint8_t iChannel); + void MIDIchangeInstrument(uint8_t iOPLChannel, uint8_t iMIDIChannel, uint8_t iNewInstrument); + void MIDIcontroller(uint8_t iChannel, uint8_t iController, uint8_t iValue); }; diff --git a/src/adplug/core/d00.cc b/src/adplug/core/d00.cc index 0b53ea0..9e90180 100644 --- a/src/adplug/core/d00.cc +++ b/src/adplug/core/d00.cc @@ -1,6 +1,6 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. - * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp@gmx.net>, et al. + * Copyright (C) 1999 - 2008 Simon Peter, <dn.tlp@gmx.net>, et al. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -34,124 +34,96 @@ #include "debug.h" #include "d00.h" -#define HIBYTE(val) (val >> 8) -#define LOBYTE(val) (val & 0xff) +#define HIBYTE(val) (val >> 8) +#define LOBYTE(val) (val & 0xff) -static const unsigned short notetable[12] = // D00 note table -{ 340, 363, 385, 408, 432, 458, 485, 514, 544, 577, 611, 647 }; +static const unsigned short notetable[12] = // D00 note table + {340,363,385,408,432,458,485,514,544,577,611,647}; -static inline uint16_t -LE_WORD (const uint16_t * val) +static inline uint16_t LE_WORD(const uint16_t *val) { - const uint8_t *b = (const uint8_t *) val; + const uint8_t *b = (const uint8_t *)val; return (b[1] << 8) + b[0]; } /*** public methods *************************************/ -CPlayer * -Cd00Player::factory (Copl * newopl) +CPlayer *Cd00Player::factory(Copl *newopl) { - return new Cd00Player (newopl); + return new Cd00Player(newopl); } -bool -Cd00Player::load (VFSFile & fd, const CFileProvider & fp) +bool Cd00Player::load(const std::string &filename, const CFileProvider &fp) { - binistream *f = fp.open (fd); - if (!f) - return false; - d00header *checkhead; - d00header1 *ch; + binistream *f = fp.open(filename); if(!f) return false; + d00header *checkhead; + d00header1 *ch; unsigned long filesize; - int i, ver1 = 0; - char *str; - std::string filename (fd.filename ()); + int i,ver1=0; + char *str; // file validation section checkhead = new d00header; - f->readString ((char *) checkhead, sizeof (d00header)); + f->readString((char *)checkhead, sizeof(d00header)); // Check for version 2-4 header - if (strncmp (checkhead->id, "JCH\x26\x02\x66", 6) || checkhead->type || - !checkhead->subsongs || checkhead->soundcard) - { + if(strncmp(checkhead->id,"JCH\x26\x02\x66",6) || checkhead->type || + !checkhead->subsongs || checkhead->soundcard) { // Check for version 0 or 1 header (and .d00 file extension) delete checkhead; - if (!fp.extension (filename, ".d00")) - { - fp.close (f); - return false; - } + if(!fp.extension(filename, ".d00")) { fp.close(f); return false; } ch = new d00header1; - f->seek (0); - f->readString ((char *) ch, sizeof (d00header1)); - if (ch->version > 1 || !ch->subsongs) - { - delete ch; - fp.close (f); - return false; - } + f->seek(0); f->readString((char *)ch, sizeof(d00header1)); + if(ch->version > 1 || !ch->subsongs) + { delete ch; fp.close(f); return false; } delete ch; ver1 = 1; - } - else + } else delete checkhead; - AdPlug_LogWrite - ("Cd00Player::load(f,\"%s\"): %s format D00 file detected!\n", - filename.c_str (), ver1 ? "Old" : "New"); + AdPlug_LogWrite("Cd00Player::load(f,\"%s\"): %s format D00 file detected!\n", + filename.c_str(), ver1 ? "Old" : "New"); // load section - filesize = fp.filesize (f); - f->seek (0); - filedata = new char[filesize + 1]; // 1 byte is needed for old-style DataInfo block - f->readString ((char *) filedata, filesize); - fp.close (f); - if (!ver1) - { // version 2 and above - header = (struct d00header *) filedata; + filesize = fp.filesize(f); f->seek(0); + filedata = new char [filesize + 1]; // 1 byte is needed for old-style DataInfo block + f->readString((char *)filedata, filesize); + fp.close(f); + if(!ver1) { // version 2 and above + header = (struct d00header *)filedata; version = header->version; - datainfo = (char *) filedata + LE_WORD (&header->infoptr); - inst = (struct Sinsts *) ((char *) filedata + LE_WORD (&header->instptr)); - seqptr = - (unsigned short *) ((char *) filedata + LE_WORD (&header->seqptr)); - for (i = 31; i >= 0; i--) // erase whitespace - if (header->songname[i] == ' ') + datainfo = (char *)filedata + LE_WORD(&header->infoptr); + inst = (struct Sinsts *)((char *)filedata + LE_WORD(&header->instptr)); + seqptr = (unsigned short *)((char *)filedata + LE_WORD(&header->seqptr)); + for(i=31;i>=0;i--) // erase whitespace + if(header->songname[i] == ' ') header->songname[i] = '\0'; else break; - for (i = 31; i >= 0; i--) - if (header->author[i] == ' ') + for(i=31;i>=0;i--) + if(header->author[i] == ' ') header->author[i] = '\0'; else break; - } - else - { // version 1 - header1 = (struct d00header1 *) filedata; + } else { // version 1 + header1 = (struct d00header1 *)filedata; version = header1->version; - datainfo = (char *) filedata + LE_WORD (&header1->infoptr); - inst = - (struct Sinsts *) ((char *) filedata + LE_WORD (&header1->instptr)); - seqptr = - (unsigned short *) ((char *) filedata + LE_WORD (&header1->seqptr)); + datainfo = (char *)filedata + LE_WORD(&header1->infoptr); + inst = (struct Sinsts *)((char *)filedata + LE_WORD(&header1->instptr)); + seqptr = (unsigned short *)((char *)filedata + LE_WORD(&header1->seqptr)); } - switch (version) - { + switch(version) { case 0: levpuls = 0; spfx = 0; - header1->speed = 70; // v0 files default to 70Hz + header1->speed = 70; // v0 files default to 70Hz break; case 1: - levpuls = - (struct Slevpuls *) ((char *) filedata + LE_WORD (&header1->lpulptr)); + levpuls = (struct Slevpuls *)((char *)filedata + LE_WORD(&header1->lpulptr)); spfx = 0; break; case 2: - levpuls = - (struct Slevpuls *) ((char *) filedata + LE_WORD (&header->spfxptr)); + levpuls = (struct Slevpuls *)((char *)filedata + LE_WORD(&header->spfxptr)); spfx = 0; break; case 3: @@ -159,401 +131,342 @@ Cd00Player::load (VFSFile & fd, const CFileProvider & fp) levpuls = 0; break; case 4: - spfx = (struct Sspfx *) ((char *) filedata + LE_WORD (&header->spfxptr)); + spfx = (struct Sspfx *)((char *)filedata + LE_WORD(&header->spfxptr)); levpuls = 0; break; } - if ((str = strstr (datainfo, "\xff\xff"))) - while ((*str == '\xff' || *str == ' ') && str >= datainfo) - { - *str = '\0'; - str--; + if((str = strstr(datainfo,"\xff\xff"))) + while((*str == '\xff' || *str == ' ') && str >= datainfo) { + *str = '\0'; str--; } - else // old-style block - memset ((char *) filedata + filesize, 0, 1); + else // old-style block + memset((char *)filedata+filesize,0,1); - rewind (0); + rewind(0); return true; } -bool -Cd00Player::update () +bool Cd00Player::update() { - unsigned char c, cnt, trackend = 0, fx, note; - unsigned short ord, *patt, buf, fxop, pattpos; + unsigned char c,cnt,trackend=0,fx,note; + unsigned short ord,*patt,buf,fxop,pattpos; // effect handling (timer dependant) - for (c = 0; c < 9; c++) - { - channel[c].slideval += channel[c].slide; - setfreq (c); // sliding - vibrato (c); // vibrato - - if (channel[c].spfx != 0xffff) - { // SpFX - if (channel[c].fxdel) + for(c=0;c<9;c++) { + channel[c].slideval += channel[c].slide; setfreq(c); // sliding + vibrato(c); // vibrato + + if(channel[c].spfx != 0xffff) { // SpFX + if(channel[c].fxdel) channel[c].fxdel--; - else - { - channel[c].spfx = LE_WORD (&spfx[channel[c].spfx].ptr); + else { + channel[c].spfx = LE_WORD(&spfx[channel[c].spfx].ptr); channel[c].fxdel = spfx[channel[c].spfx].duration; - channel[c].inst = LE_WORD (&spfx[channel[c].spfx].instnr) & 0xfff; - if (spfx[channel[c].spfx].modlev != 0xff) + channel[c].inst = LE_WORD(&spfx[channel[c].spfx].instnr) & 0xfff; + if(spfx[channel[c].spfx].modlev != 0xff) channel[c].modvol = spfx[channel[c].spfx].modlev; - setinst (c); - if (LE_WORD (&spfx[channel[c].spfx].instnr) & 0x8000) // locked frequency + setinst(c); + if(LE_WORD(&spfx[channel[c].spfx].instnr) & 0x8000) // locked frequency note = spfx[channel[c].spfx].halfnote; - else // unlocked frequency + else // unlocked frequency note = spfx[channel[c].spfx].halfnote + channel[c].note; - channel[c].freq = notetable[note % 12] + ((note / 12) << 10); - setfreq (c); + channel[c].freq = notetable[note%12] + ((note/12) << 10); + setfreq(c); } - channel[c].modvol += spfx[channel[c].spfx].modlevadd; - channel[c].modvol &= 63; - setvolume (c); + channel[c].modvol += spfx[channel[c].spfx].modlevadd; channel[c].modvol &= 63; + setvolume(c); } - if (channel[c].levpuls != 0xff) // Levelpuls - { - if (channel[c].frameskip) + if(channel[c].levpuls != 0xff) { // Levelpuls + if(channel[c].frameskip) channel[c].frameskip--; - else - { + else { channel[c].frameskip = inst[channel[c].inst].timer; - if (channel[c].fxdel) + if(channel[c].fxdel) channel[c].fxdel--; - else - { + else { channel[c].levpuls = levpuls[channel[c].levpuls].ptr - 1; channel[c].fxdel = levpuls[channel[c].levpuls].duration; - if (levpuls[channel[c].levpuls].level != 0xff) + if(levpuls[channel[c].levpuls].level != 0xff) channel[c].modvol = levpuls[channel[c].levpuls].level; } - channel[c].modvol += levpuls[channel[c].levpuls].voladd; - channel[c].modvol &= 63; - setvolume (c); + channel[c].modvol += levpuls[channel[c].levpuls].voladd; channel[c].modvol &= 63; + setvolume(c); } } } // song handling - for (c = 0; c < 9; c++) - if (version < 3 ? channel[c].del : channel[c].del <= 0x7f) - { - if (version == 4) // v4: hard restart SR - if (channel[c].del == inst[channel[c].inst].timer) - if (channel[c].nextnote) - opl->write (0x83 + op_table[c], inst[channel[c].inst].sr); - if (version < 3) + for(c=0;c<9;c++) + if(version < 3 ? channel[c].del : channel[c].del <= 0x7f) { + if(version == 4) // v4: hard restart SR + if(channel[c].del == inst[channel[c].inst].timer) + if(channel[c].nextnote) + opl->write(0x83 + op_table[c], inst[channel[c].inst].sr); + if(version < 3) channel[c].del--; - else if (channel[c].speed) - channel[c].del += channel[c].speed; else - { - channel[c].seqend = 1; - continue; - } - } - else - { - if (channel[c].speed) - { - if (version < 3) + if(channel[c].speed) + channel[c].del += channel[c].speed; + else { + channel[c].seqend = 1; + continue; + } + } else { + if(channel[c].speed) { + if(version < 3) channel[c].del = channel[c].speed; - else - { + else { channel[c].del &= 0x7f; channel[c].del += channel[c].speed; } - } - else - { + } else { channel[c].seqend = 1; continue; } - if (channel[c].rhcnt) - { // process pending REST/HOLD events + if(channel[c].rhcnt) { // process pending REST/HOLD events channel[c].rhcnt--; continue; } - readorder: // process arrangement (orderlist) - ord = LE_WORD (&channel[c].order[channel[c].ordpos]); - switch (ord) - { - case 0xfffe: - channel[c].seqend = 1; - continue; // end of arrangement stream - case 0xffff: // jump to order - channel[c].ordpos = - LE_WORD (&channel[c].order[channel[c].ordpos + 1]); + readorder: // process arrangement (orderlist) + ord = LE_WORD(&channel[c].order[channel[c].ordpos]); + switch(ord) { + case 0xfffe: channel[c].seqend = 1; continue; // end of arrangement stream + case 0xffff: // jump to order + channel[c].ordpos = LE_WORD(&channel[c].order[channel[c].ordpos + 1]); channel[c].seqend = 1; goto readorder; default: - if (ord >= 0x9000) - { // set speed + if(ord >= 0x9000) { // set speed channel[c].speed = ord & 0xff; - ord = LE_WORD (&channel[c].order[channel[c].ordpos - 1]); + ord = LE_WORD(&channel[c].order[channel[c].ordpos - 1]); channel[c].ordpos++; - } - else if (ord >= 0x8000) - { // transpose track - channel[c].transpose = ord & 0xff; - if (ord & 0x100) - channel[c].transpose = -channel[c].transpose; - ord = LE_WORD (&channel[c].order[++channel[c].ordpos]); - } - patt = - (unsigned short *) ((char *) filedata + LE_WORD (&seqptr[ord])); + } else + if(ord >= 0x8000) { // transpose track + channel[c].transpose = ord & 0xff; + if(ord & 0x100) + channel[c].transpose = -channel[c].transpose; + ord = LE_WORD(&channel[c].order[++channel[c].ordpos]); + } + patt = (unsigned short *)((char *)filedata + LE_WORD(&seqptr[ord])); break; } - channel[c].fxflag = 0; - readseq: // process sequence (pattern) - if (!version) // v0: always initialize rhcnt + channel[c].fxflag = 0; + readseq: // process sequence (pattern) + if(!version) // v0: always initialize rhcnt channel[c].rhcnt = channel[c].irhcnt; - pattpos = LE_WORD (&patt[channel[c].pattpos]); - if (pattpos == 0xffff) - { // pattern ended? + pattpos = LE_WORD(&patt[channel[c].pattpos]); + if(pattpos == 0xffff) { // pattern ended? channel[c].pattpos = 0; channel[c].ordpos++; goto readorder; } - cnt = HIBYTE (pattpos); - note = LOBYTE (pattpos); + cnt = HIBYTE(pattpos); + note = LOBYTE(pattpos); fx = pattpos >> 12; fxop = pattpos & 0x0fff; - channel[c].pattpos++; - pattpos = LE_WORD (&patt[channel[c].pattpos]); - channel[c].nextnote = LOBYTE (pattpos) & 0x7f; - if (version ? cnt < 0x40 : !fx) - { // note event - switch (note) - { - case 0: // REST event + channel[c].pattpos++; pattpos = LE_WORD(&patt[channel[c].pattpos]); + channel[c].nextnote = LOBYTE(pattpos) & 0x7f; + if(version ? cnt < 0x40 : !fx) { // note event + switch(note) { + case 0: // REST event case 0x80: - if (!note || version) - { + if(!note || version) { channel[c].key = 0; - setfreq (c); + setfreq(c); } // fall through... - case 0x7e: // HOLD event - if (version) + case 0x7e: // HOLD event + if(version) channel[c].rhcnt = cnt; channel[c].nextnote = 0; break; - default: // play note + default: // play note // restart fx - if (!(channel[c].fxflag & 1)) + if(!(channel[c].fxflag & 1)) channel[c].vibdepth = 0; - if (!(channel[c].fxflag & 2)) + if(!(channel[c].fxflag & 2)) channel[c].slideval = channel[c].slide = 0; - if (version) - { // note handling for v1 and above - if (note > 0x80) // locked note (no channel transpose) + if(version) { // note handling for v1 and above + if(note > 0x80) // locked note (no channel transpose) note -= 0x80; - else // unlocked note + else // unlocked note note += channel[c].transpose; - channel[c].note = note; // remember note for SpFX + channel[c].note = note; // remember note for SpFX - if (channel[c].ispfx != 0xffff && cnt < 0x20) - { // reset SpFX + if(channel[c].ispfx != 0xffff && cnt < 0x20) { // reset SpFX channel[c].spfx = channel[c].ispfx; - if (LE_WORD (&spfx[channel[c].spfx].instnr) & 0x8000) // locked frequency + if(LE_WORD(&spfx[channel[c].spfx].instnr) & 0x8000) // locked frequency note = spfx[channel[c].spfx].halfnote; - else // unlocked frequency + else // unlocked frequency note += spfx[channel[c].spfx].halfnote; - channel[c].inst = - LE_WORD (&spfx[channel[c].spfx].instnr) & 0xfff; + channel[c].inst = LE_WORD(&spfx[channel[c].spfx].instnr) & 0xfff; channel[c].fxdel = spfx[channel[c].spfx].duration; - if (spfx[channel[c].spfx].modlev != 0xff) + if(spfx[channel[c].spfx].modlev != 0xff) channel[c].modvol = spfx[channel[c].spfx].modlev; else channel[c].modvol = inst[channel[c].inst].data[7] & 63; } - if (channel[c].ilevpuls != 0xff && cnt < 0x20) - { // reset LevelPuls + if(channel[c].ilevpuls != 0xff && cnt < 0x20) { // reset LevelPuls channel[c].levpuls = channel[c].ilevpuls; channel[c].fxdel = levpuls[channel[c].levpuls].duration; channel[c].frameskip = inst[channel[c].inst].timer; - if (levpuls[channel[c].levpuls].level != 0xff) + if(levpuls[channel[c].levpuls].level != 0xff) channel[c].modvol = levpuls[channel[c].levpuls].level; else channel[c].modvol = inst[channel[c].inst].data[7] & 63; } - channel[c].freq = notetable[note % 12] + ((note / 12) << 10); - if (cnt < 0x20) // normal note - playnote (c); - else - { // tienote - setfreq (c); + channel[c].freq = notetable[note%12] + ((note/12) << 10); + if(cnt < 0x20) // normal note + playnote(c); + else { // tienote + setfreq(c); cnt -= 0x20; // make count proper } channel[c].rhcnt = cnt; - } - else - { // note handling for v0 - if (cnt < 2) // unlocked note + } else { // note handling for v0 + if(cnt < 2) // unlocked note note += channel[c].transpose; channel[c].note = note; - channel[c].freq = notetable[note % 12] + ((note / 12) << 10); - if (cnt == 1) // tienote - setfreq (c); - else // normal note - playnote (c); + channel[c].freq = notetable[note%12] + ((note/12) << 10); + if(cnt == 1) // tienote + setfreq(c); + else // normal note + playnote(c); } break; } - continue; // event is complete - } - else - { // effect event - switch (fx) - { - case 6: // Cut/Stop Voice + continue; // event is complete + } else { // effect event + switch(fx) { + case 6: // Cut/Stop Voice buf = channel[c].inst; channel[c].inst = 0; - playnote (c); + playnote(c); channel[c].inst = buf; channel[c].rhcnt = fxop; - continue; // no note follows this event - case 7: // Vibrato + continue; // no note follows this event + case 7: // Vibrato channel[c].vibspeed = fxop & 0xff; channel[c].vibdepth = fxop >> 8; channel[c].trigger = fxop >> 9; channel[c].fxflag |= 1; break; - case 8: // v0: Duration - if (!version) + case 8: // v0: Duration + if(!version) channel[c].irhcnt = fxop; break; - case 9: // New Level + case 9: // New Level channel[c].vol = fxop & 63; - if (channel[c].vol + channel[c].cvol < 63) // apply channel volume + if(channel[c].vol + channel[c].cvol < 63) // apply channel volume channel[c].vol += channel[c].cvol; else channel[c].vol = 63; - setvolume (c); + setvolume(c); break; - case 0xb: // v4: Set SpFX - if (version == 4) + case 0xb: // v4: Set SpFX + if(version == 4) channel[c].ispfx = fxop; break; - case 0xc: // Set Instrument + case 0xc: // Set Instrument channel[c].ispfx = 0xffff; channel[c].spfx = 0xffff; channel[c].inst = fxop; channel[c].modvol = inst[fxop].data[7] & 63; - if (version < 3 && version && inst[fxop].tunelev) // Set LevelPuls + if(version < 3 && version && inst[fxop].tunelev) // Set LevelPuls channel[c].ilevpuls = inst[fxop].tunelev - 1; - else - { + else { channel[c].ilevpuls = 0xff; channel[c].levpuls = 0xff; } break; - case 0xd: // Slide up + case 0xd: // Slide up channel[c].slide = fxop; channel[c].fxflag |= 2; break; - case 0xe: // Slide down + case 0xe: // Slide down channel[c].slide = -fxop; channel[c].fxflag |= 2; break; } - goto readseq; // event is incomplete, note follows + goto readseq; // event is incomplete, note follows } } - for (c = 0; c < 9; c++) - if (channel[c].seqend) + for(c=0;c<9;c++) + if(channel[c].seqend) trackend++; - if (trackend == 9) + if(trackend == 9) songend = 1; return !songend; } -void -Cd00Player::rewind (int subsong) +void Cd00Player::rewind(int subsong) { - struct Stpoin - { + struct Stpoin { unsigned short ptr[9]; - unsigned char volume[9], dummy[5]; + unsigned char volume[9],dummy[5]; } *tpoin; int i; if(subsong == -1) subsong = cursubsong; - if (version > 1) - { // do nothing if subsong > number of subsongs - if (subsong >= header->subsongs) + if(version > 1) { // do nothing if subsong > number of subsongs + if(subsong >= header->subsongs) + return; + } else + if(subsong >= header1->subsongs) return; - } - else if (subsong >= header1->subsongs) - return; - memset (channel, 0, sizeof (channel)); - if (version > 1) - tpoin = (struct Stpoin *) ((char *) filedata + LE_WORD (&header->tpoin)); + memset(channel,0,sizeof(channel)); + if(version > 1) + tpoin = (struct Stpoin *)((char *)filedata + LE_WORD(&header->tpoin)); else - tpoin = (struct Stpoin *) ((char *) filedata + LE_WORD (&header1->tpoin)); - for (i = 0; i < 9; i++) - { - if (LE_WORD (&tpoin[subsong].ptr[i])) - { // track enabled - channel[i].speed = LE_WORD ((unsigned short *) - ((char *) filedata + - LE_WORD (&tpoin[subsong].ptr[i]))); - channel[i].order = - (unsigned short *) ((char *) filedata + - LE_WORD (&tpoin[subsong].ptr[i]) + 2); - } - else - { // track disabled + tpoin = (struct Stpoin *)((char *)filedata + LE_WORD(&header1->tpoin)); + for(i=0;i<9;i++) { + if(LE_WORD(&tpoin[subsong].ptr[i])) { // track enabled + channel[i].speed = LE_WORD((unsigned short *) + ((char *)filedata + LE_WORD(&tpoin[subsong].ptr[i]))); + channel[i].order = (unsigned short *) + ((char *)filedata + LE_WORD(&tpoin[subsong].ptr[i]) + 2); + } else { // track disabled channel[i].speed = 0; channel[i].order = 0; } - channel[i].ispfx = 0xffff; - channel[i].spfx = 0xffff; // no SpFX - channel[i].ilevpuls = 0xff; - channel[i].levpuls = 0xff; // no LevelPuls + channel[i].ispfx = 0xffff; channel[i].spfx = 0xffff; // no SpFX + channel[i].ilevpuls = 0xff; channel[i].levpuls = 0xff; // no LevelPuls channel[i].cvol = tpoin[subsong].volume[i] & 0x7f; // our player may savely ignore bit 7 - channel[i].vol = channel[i].cvol; // initialize volume + channel[i].vol = channel[i].cvol; // initialize volume } songend = 0; - opl->init (); - opl->write (1, 32); // reset OPL chip + opl->init(); opl->write(1,32); // reset OPL chip cursubsong = subsong; } -std::string Cd00Player::gettype () +std::string Cd00Player::gettype() { - char - tmpstr[40]; + char tmpstr[40]; - sprintf (tmpstr, "EdLib packed (version %d)", - version > 1 ? header->version : header1->version); - return std::string (tmpstr); + sprintf(tmpstr,"EdLib packed (version %d)",version > 1 ? header->version : header1->version); + return std::string(tmpstr); } -float -Cd00Player::getrefresh () +float Cd00Player::getrefresh() { - if (version > 1) + if(version > 1) return header->speed; else return header1->speed; } -unsigned int -Cd00Player::getsubsongs () +unsigned int Cd00Player::getsubsongs() { - if (version <= 1) // return number of subsongs + if(version <= 1) // return number of subsongs return header1->subsongs; else return header->subsongs; @@ -561,93 +474,76 @@ Cd00Player::getsubsongs () /*** private methods *************************************/ -void -Cd00Player::setvolume (unsigned char chan) +void Cd00Player::setvolume(unsigned char chan) { unsigned char op = op_table[chan]; - unsigned short insnr = channel[chan].inst; - - opl->write (0x43 + op, - (int) (63 - - ((63 - (inst[insnr].data[2] & 63)) / 63.0) * (63 - - channel - [chan]. - vol)) + - (inst[insnr].data[2] & 192)); - if (inst[insnr].data[10] & 1) - opl->write (0x40 + op, - (int) (63 - - ((63 - channel[chan].modvol) / 63.0) * (63 - - channel[chan]. - vol)) + - (inst[insnr].data[7] & 192)); + unsigned short insnr = channel[chan].inst; + + opl->write(0x43 + op,(int)(63-((63-(inst[insnr].data[2] & 63))/63.0)*(63-channel[chan].vol)) + + (inst[insnr].data[2] & 192)); + if(inst[insnr].data[10] & 1) + opl->write(0x40 + op,(int)(63-((63-channel[chan].modvol)/63.0)*(63-channel[chan].vol)) + + (inst[insnr].data[7] & 192)); else - opl->write (0x40 + op, - channel[chan].modvol + (inst[insnr].data[7] & 192)); + opl->write(0x40 + op,channel[chan].modvol + (inst[insnr].data[7] & 192)); } -void -Cd00Player::setfreq (unsigned char chan) +void Cd00Player::setfreq(unsigned char chan) { unsigned short freq = channel[chan].freq; - if (version == 4) // v4: apply instrument finetune + if(version == 4) // v4: apply instrument finetune freq += inst[channel[chan].inst].tunelev; freq += channel[chan].slideval; - opl->write (0xa0 + chan, freq & 255); - if (channel[chan].key) - opl->write (0xb0 + chan, ((freq >> 8) & 31) | 32); + opl->write(0xa0 + chan, freq & 255); + if(channel[chan].key) + opl->write(0xb0 + chan, ((freq >> 8) & 31) | 32); else - opl->write (0xb0 + chan, (freq >> 8) & 31); + opl->write(0xb0 + chan, (freq >> 8) & 31); } -void -Cd00Player::setinst (unsigned char chan) +void Cd00Player::setinst(unsigned char chan) { unsigned char op = op_table[chan]; - unsigned short insnr = channel[chan].inst; + unsigned short insnr = channel[chan].inst; // set instrument data - opl->write (0x63 + op, inst[insnr].data[0]); - opl->write (0x83 + op, inst[insnr].data[1]); - opl->write (0x23 + op, inst[insnr].data[3]); - opl->write (0xe3 + op, inst[insnr].data[4]); - opl->write (0x60 + op, inst[insnr].data[5]); - opl->write (0x80 + op, inst[insnr].data[6]); - opl->write (0x20 + op, inst[insnr].data[8]); - opl->write (0xe0 + op, inst[insnr].data[9]); - if (version) - opl->write (0xc0 + chan, inst[insnr].data[10]); + opl->write(0x63 + op, inst[insnr].data[0]); + opl->write(0x83 + op, inst[insnr].data[1]); + opl->write(0x23 + op, inst[insnr].data[3]); + opl->write(0xe3 + op, inst[insnr].data[4]); + opl->write(0x60 + op, inst[insnr].data[5]); + opl->write(0x80 + op, inst[insnr].data[6]); + opl->write(0x20 + op, inst[insnr].data[8]); + opl->write(0xe0 + op, inst[insnr].data[9]); + if(version) + opl->write(0xc0 + chan, inst[insnr].data[10]); else - opl->write (0xc0 + chan, - (inst[insnr].data[10] << 1) + (inst[insnr].tunelev & 1)); + opl->write(0xc0 + chan, (inst[insnr].data[10] << 1) + (inst[insnr].tunelev & 1)); } -void -Cd00Player::playnote (unsigned char chan) +void Cd00Player::playnote(unsigned char chan) { // set misc vars & play - opl->write (0xb0 + chan, 0); // stop old note - setinst (chan); + opl->write(0xb0 + chan, 0); // stop old note + setinst(chan); channel[chan].key = 1; - setfreq (chan); - setvolume (chan); + setfreq(chan); + setvolume(chan); } -void -Cd00Player::vibrato (unsigned char chan) +void Cd00Player::vibrato(unsigned char chan) { - if (!channel[chan].vibdepth) + if(!channel[chan].vibdepth) return; - if (channel[chan].trigger) + if(channel[chan].trigger) channel[chan].trigger--; - else - { + else { channel[chan].trigger = channel[chan].vibdepth; channel[chan].vibspeed = -channel[chan].vibspeed; } channel[chan].freq += channel[chan].vibspeed; - setfreq (chan); + setfreq(chan); } diff --git a/src/adplug/core/d00.h b/src/adplug/core/d00.h index 2071c2f..8737d76 100644 --- a/src/adplug/core/d00.h +++ b/src/adplug/core/d00.h @@ -1,17 +1,17 @@ /* * AdPlug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -29,79 +29,81 @@ class Cd00Player: public CPlayer public: static CPlayer *factory(Copl *newopl); - Cd00Player(Copl *newopl) - : CPlayer(newopl), filedata(0) - { }; - ~Cd00Player() - { if(filedata) delete [] filedata; }; + Cd00Player(Copl *newopl) + : CPlayer(newopl), filedata(0) + { }; + ~Cd00Player() + { if(filedata) delete [] filedata; }; - bool load(VFSFile &fd, const CFileProvider &fp); - bool update(); - void rewind(int subsong); - float getrefresh(); + bool load(const std::string &filename, const CFileProvider &fp); + bool update(); + void rewind(int subsong); + float getrefresh(); - std::string gettype(); - std::string gettitle() - { if(version > 1) return std::string(header->songname); else return std::string(); }; - std::string getauthor() - { if(version > 1) return std::string(header->author); else return std::string(); }; - std::string getdesc() - { if(*datainfo) return std::string(datainfo); else return std::string(); }; - unsigned int getsubsongs(); + std::string gettype(); + std::string gettitle() + { if(version > 1) return std::string(header->songname); else return std::string(); }; + std::string getauthor() + { if(version > 1) return std::string(header->author); else return std::string(); }; + std::string getdesc() + { if(*datainfo) return std::string(datainfo); else return std::string(); }; + unsigned int getsubsongs(); protected: #pragma pack(1) - struct d00header { - char id[6]; - unsigned char type,version,speed,subsongs,soundcard; - char songname[32],author[32],dummy[32]; - unsigned short tpoin,seqptr,instptr,infoptr,spfxptr,endmark; - }; + struct d00header { + char id[6]; + unsigned char type,version,speed,subsongs,soundcard; + char songname[32],author[32],dummy[32]; + unsigned short tpoin,seqptr,instptr,infoptr,spfxptr,endmark; + }; - struct d00header1 { - unsigned char version,speed,subsongs; - unsigned short tpoin,seqptr,instptr,infoptr,lpulptr,endmark; - }; + struct d00header1 { + unsigned char version,speed,subsongs; + unsigned short tpoin,seqptr,instptr,infoptr,lpulptr,endmark; + }; #pragma pack() - struct { - unsigned short *order,ordpos,pattpos,del,speed,rhcnt,key,freq,inst,spfx,ispfx,irhcnt; - signed short transpose,slide,slideval,vibspeed; - unsigned char seqend,vol,vibdepth,fxdel,modvol,cvol,levpuls,frameskip,nextnote,note,ilevpuls,trigger,fxflag; - } channel[9]; + struct { + unsigned short *order,ordpos,pattpos,del,speed,rhcnt,key,freq,inst, + spfx,ispfx,irhcnt; + signed short transpose,slide,slideval,vibspeed; + unsigned char seqend,vol,vibdepth,fxdel,modvol,cvol,levpuls, + frameskip,nextnote,note,ilevpuls,trigger,fxflag; + } channel[9]; - struct Sinsts { - unsigned char data[11],tunelev,timer,sr,dummy[2]; - } *inst; + struct Sinsts { + unsigned char data[11],tunelev,timer,sr,dummy[2]; + } *inst; - struct Sspfx { - unsigned short instnr; - signed char halfnote; - unsigned char modlev; - signed char modlevadd; - unsigned char duration; - unsigned short ptr; - } *spfx; + struct Sspfx { + unsigned short instnr; + signed char halfnote; + unsigned char modlev; + signed char modlevadd; + unsigned char duration; + unsigned short ptr; + } *spfx; - struct Slevpuls { - unsigned char level; - signed char voladd; - unsigned char duration,ptr; - } *levpuls; + struct Slevpuls { + unsigned char level; + signed char voladd; + unsigned char duration,ptr; + } *levpuls; - unsigned char songend,version,cursubsong; - char *datainfo; - unsigned short *seqptr; - d00header *header; - d00header1 *header1; - char *filedata; + unsigned char songend,version,cursubsong; + char *datainfo; + unsigned short *seqptr; + d00header *header; + d00header1 *header1; + char *filedata; private: - void setvolume(unsigned char chan); - void setfreq(unsigned char chan); - void setinst(unsigned char chan); - void playnote(unsigned char chan); - void vibrato(unsigned char chan); + void setvolume(unsigned char chan); + void setfreq(unsigned char chan); + void setinst(unsigned char chan); + void playnote(unsigned char chan); + void vibrato(unsigned char chan); }; #endif diff --git a/src/adplug/core/database.cc b/src/adplug/core/database.cc index 035c284..d4a27e1 100644 --- a/src/adplug/core/database.cc +++ b/src/adplug/core/database.cc @@ -1,17 +1,17 @@ /* * AdPlug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (c) 1999 - 2006 Simon Peter <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -21,123 +21,108 @@ * Copyright (c) 2002, 2003, 2006 Simon Peter <dn.tlp@gmx.net> */ -#include "binio_virtual.h" +#include "binio.h" +#include "binfile.h" #include <string.h> #include "database.h" -#define DB_FILEID_V10 "AdPlug Module Information Database 1.0\x10" +#define DB_FILEID_V10 "AdPlug Module Information Database 1.0\x10" /***** CAdPlugDatabase *****/ -const unsigned short - CAdPlugDatabase::hash_radix = 0xfff1; // should be prime +const unsigned short CAdPlugDatabase::hash_radix = 0xfff1; // should be prime -CAdPlugDatabase::CAdPlugDatabase ():linear_index (0), linear_logic_length (0), -linear_length (0) +CAdPlugDatabase::CAdPlugDatabase() + : linear_index(0), linear_logic_length(0), linear_length(0) { - db_linear = new DB_Bucket *[hash_radix]; - db_hashed = new DB_Bucket *[hash_radix]; - memset (db_linear, 0, sizeof (DB_Bucket *) * hash_radix); - memset (db_hashed, 0, sizeof (DB_Bucket *) * hash_radix); + db_linear = new DB_Bucket * [hash_radix]; + db_hashed = new DB_Bucket * [hash_radix]; + memset(db_linear, 0, sizeof(DB_Bucket *) * hash_radix); + memset(db_hashed, 0, sizeof(DB_Bucket *) * hash_radix); } -CAdPlugDatabase::~CAdPlugDatabase () +CAdPlugDatabase::~CAdPlugDatabase() { unsigned long i; - for (i = 0; i < linear_length; i++) + for(i = 0; i < linear_length; i++) delete db_linear[i]; - delete[]db_linear; - delete[]db_hashed; + delete [] db_linear; + delete [] db_hashed; } -bool -CAdPlugDatabase::load (std::string db_name) +bool CAdPlugDatabase::load(std::string db_name) { - vfsistream f (db_name); - if (f.error ()) - return false; - return load (f); + binifstream f(db_name); + if(f.error()) return false; + return load(f); } -bool -CAdPlugDatabase::load (binistream & f) +bool CAdPlugDatabase::load(binistream &f) { - unsigned int idlen = strlen (DB_FILEID_V10); - char *id = new char[idlen]; + unsigned int idlen = strlen(DB_FILEID_V10); + char *id = new char [idlen]; unsigned long length; // Open database as little endian with IEEE floats - f.setFlag (binio::BigEndian, false); - f.setFlag (binio::FloatIEEE); + f.setFlag(binio::BigEndian, false); f.setFlag(binio::FloatIEEE); - f.readString (id, idlen); - if (memcmp (id, DB_FILEID_V10, idlen)) - { - delete[]id; + f.readString(id,idlen); + if(memcmp(id,DB_FILEID_V10,idlen)) { + delete [] id; return false; } - delete[]id; - length = f.readInt (4); + delete [] id; + length = f.readInt(4); // read records - for (unsigned long i = 0; i < length; i++) - insert (CRecord::factory (f)); + for(unsigned long i = 0; i < length; i++) + insert(CRecord::factory(f)); return true; } -bool -CAdPlugDatabase::save (std::string db_name) +bool CAdPlugDatabase::save(std::string db_name) { - vfsostream f (db_name); - if (f.error ()) - return false; - return save (f); + binofstream f(db_name); + if(f.error()) return false; + return save(f); } -bool -CAdPlugDatabase::save (binostream & f) +bool CAdPlugDatabase::save(binostream &f) { unsigned long i; // Save database as little endian with IEEE floats - f.setFlag (binio::BigEndian, false); - f.setFlag (binio::FloatIEEE); + f.setFlag(binio::BigEndian, false); f.setFlag(binio::FloatIEEE); - f.writeString (DB_FILEID_V10); - f.writeInt (linear_logic_length, 4); + f.writeString(DB_FILEID_V10); + f.writeInt(linear_logic_length, 4); // write records - for (i = 0; i < linear_length; i++) - if (!db_linear[i]->deleted) - db_linear[i]->record->write (f); + for(i = 0; i < linear_length; i++) + if(!db_linear[i]->deleted) + db_linear[i]->record->write(f); return true; } -CAdPlugDatabase::CRecord * CAdPlugDatabase::search (CKey const &key) +CAdPlugDatabase::CRecord *CAdPlugDatabase::search(CKey const &key) { - if (lookup (key)) - return get_record (); - else - return 0; + if(lookup(key)) return get_record(); else return 0; } -bool -CAdPlugDatabase::lookup (CKey const &key) +bool CAdPlugDatabase::lookup(CKey const &key) { - unsigned long index = make_hash (key); - if (!db_hashed[index]) - return false; + unsigned long index = make_hash(key); + if(!db_hashed[index]) return false; // immediate hit ? DB_Bucket *bucket = db_hashed[index]; - if (!bucket->deleted && bucket->record->key == key) - { + if(!bucket->deleted && bucket->record->key == key) { linear_index = bucket->index; return true; } @@ -145,10 +130,8 @@ CAdPlugDatabase::lookup (CKey const &key) // in-chain hit ? bucket = db_hashed[index]->chain; - while (bucket) - { - if (!bucket->deleted && bucket->record->key == key) - { + while(bucket) { + if(!bucket->deleted && bucket->record->key == key) { linear_index = bucket->index; return true; } @@ -159,320 +142,248 @@ CAdPlugDatabase::lookup (CKey const &key) return false; } -bool -CAdPlugDatabase::insert (CRecord * record) +bool CAdPlugDatabase::insert(CRecord *record) { long index; // sanity checks - if (!record) - return false; // null-pointer given - if (linear_length == hash_radix) - return false; // max. db size exceeded - if (lookup (record->key)) - return false; // record already in db + if(!record) return false; // null-pointer given + if(linear_length == hash_radix) return false; // max. db size exceeded + if(lookup(record->key)) return false; // record already in db // make bucket - DB_Bucket *bucket = new DB_Bucket (linear_length, record); - if (!bucket) - return false; + DB_Bucket *bucket = new DB_Bucket(linear_length, record); + if(!bucket) return false; // add to linear list db_linear[linear_length] = bucket; - linear_logic_length++; - linear_length++; + linear_logic_length++; linear_length++; // add to hashed list - index = make_hash (record->key); + index = make_hash(record->key); - if (!db_hashed[index]) // First entry in hashtable + if(!db_hashed[index]) // First entry in hashtable db_hashed[index] = bucket; - else - { // Add entry in chained list + else { // Add entry in chained list DB_Bucket *chain = db_hashed[index]; - while (chain->chain) - chain = chain->chain; + while(chain->chain) chain = chain->chain; chain->chain = bucket; } return true; } -void -CAdPlugDatabase::wipe (CRecord * record) +void CAdPlugDatabase::wipe(CRecord *record) { - if (!lookup (record->key)) - return; - wipe (); + if(!lookup(record->key)) return; + wipe(); } -void -CAdPlugDatabase::wipe () +void CAdPlugDatabase::wipe() { - if (!linear_length) - return; + if(!linear_length) return; DB_Bucket *bucket = db_linear[linear_index]; - if (!bucket->deleted) - { + if(!bucket->deleted) { delete bucket->record; linear_logic_length--; bucket->deleted = true; } } -CAdPlugDatabase::CRecord * CAdPlugDatabase::get_record () +CAdPlugDatabase::CRecord *CAdPlugDatabase::get_record() { - if (!linear_length) - return 0; + if(!linear_length) return 0; return db_linear[linear_index]->record; } -bool -CAdPlugDatabase::go_forward () +bool CAdPlugDatabase::go_forward() { - if (linear_index + 1 < linear_length) - { + if(linear_index + 1 < linear_length) { linear_index++; return true; - } - else + } else return false; } -bool -CAdPlugDatabase::go_backward () +bool CAdPlugDatabase::go_backward() { - if (!linear_index) - return false; + if(!linear_index) return false; linear_index--; return true; } -void -CAdPlugDatabase::goto_begin () +void CAdPlugDatabase::goto_begin() { - if (linear_length) - linear_index = 0; + if(linear_length) linear_index = 0; } -void -CAdPlugDatabase::goto_end () +void CAdPlugDatabase::goto_end() { - if (linear_length) - linear_index = linear_length - 1; + if(linear_length) linear_index = linear_length - 1; } -inline unsigned long -CAdPlugDatabase::make_hash (CKey const &key) +inline unsigned long CAdPlugDatabase::make_hash(CKey const &key) { return (key.crc32 + key.crc16) % hash_radix; } /***** CAdPlugDatabase::DB_Bucket *****/ -CAdPlugDatabase::DB_Bucket::DB_Bucket (unsigned long nindex, CRecord * newrecord, DB_Bucket * newchain):index (nindex), deleted (false), chain (newchain), -record -(newrecord) +CAdPlugDatabase::DB_Bucket::DB_Bucket(unsigned long nindex, CRecord *newrecord, DB_Bucket *newchain) + : index(nindex), deleted(false), chain(newchain), record(newrecord) { } -CAdPlugDatabase::DB_Bucket::~DB_Bucket () +CAdPlugDatabase::DB_Bucket::~DB_Bucket() { - if (!deleted) - delete - record; + if(!deleted) delete record; } /***** CAdPlugDatabase::CRecord *****/ -CAdPlugDatabase::CRecord * CAdPlugDatabase::CRecord::factory (RecordType type) -{ - switch (type) - { - case Plain: - return new CPlainRecord; - case SongInfo: - return new CInfoRecord; - case ClockSpeed: - return new CClockRecord; - default: - return 0; +CAdPlugDatabase::CRecord *CAdPlugDatabase::CRecord::factory(RecordType type) +{ + switch(type) { + case Plain: return new CPlainRecord; + case SongInfo: return new CInfoRecord; + case ClockSpeed: return new CClockRecord; + default: return 0; } } -CAdPlugDatabase::CRecord * CAdPlugDatabase::CRecord::factory (binistream & in) +CAdPlugDatabase::CRecord *CAdPlugDatabase::CRecord::factory(binistream &in) { - RecordType - type; - unsigned long - size; - CRecord * - rec; + RecordType type; + unsigned long size; + CRecord *rec; - type = (RecordType) in.readInt (1); - size = in.readInt (4); - rec = factory (type); + type = (RecordType)in.readInt(1); size = in.readInt(4); + rec = factory(type); - if (rec) - { - rec->key.crc16 = in.readInt (2); - rec->key.crc32 = in.readInt (4); - rec->filetype = in.readString ('\0'); - rec->comment = in.readString ('\0'); - rec->read_own (in); + if(rec) { + rec->key.crc16 = in.readInt(2); rec->key.crc32 = in.readInt(4); + rec->filetype = in.readString('\0'); rec->comment = in.readString('\0'); + rec->read_own(in); return rec; - } - else - { + } else { // skip this record, cause we don't know about it - in.seek (size, binio::Add); + in.seek(size, binio::Add); return 0; } } -void -CAdPlugDatabase::CRecord::write (binostream & out) +void CAdPlugDatabase::CRecord::write(binostream &out) { - out.writeInt (type, 1); - out.writeInt (get_size () + filetype.length () + comment.length () + 8, 4); - out.writeInt (key.crc16, 2); - out.writeInt (key.crc32, 4); - out.writeString (filetype); - out.writeInt ('\0', 1); - out.writeString (comment); - out.writeInt ('\0', 1); + out.writeInt(type, 1); + out.writeInt(get_size() + filetype.length() + comment.length() + 8, 4); + out.writeInt(key.crc16, 2); out.writeInt(key.crc32, 4); + out.writeString(filetype); out.writeInt('\0', 1); + out.writeString(comment); out.writeInt('\0', 1); - write_own (out); + write_own(out); } -bool -CAdPlugDatabase::CRecord::user_read (std::istream & in, std::ostream & out) +bool CAdPlugDatabase::CRecord::user_read(std::istream &in, std::ostream &out) { - return user_read_own (in, out); + return user_read_own(in, out); } -bool -CAdPlugDatabase::CRecord::user_write (std::ostream & out) +bool CAdPlugDatabase::CRecord::user_write(std::ostream &out) { out << "Record type: "; - switch (type) - { - case Plain: - out << "Plain"; - break; - case SongInfo: - out << "SongInfo"; - break; - case ClockSpeed: - out << "ClockSpeed"; - break; - default: - out << "*** Unknown ***"; - break; + switch(type) { + case Plain: out << "Plain"; break; + case SongInfo: out << "SongInfo"; break; + case ClockSpeed: out << "ClockSpeed"; break; + default: out << "*** Unknown ***"; break; } out << std::endl; - out << "Key: " << std::hex << key.crc16 << ":" << key. - crc32 << std::dec << std::endl; + out << "Key: " << std::hex << key.crc16 << ":" << key.crc32 << std::dec << std::endl; out << "File type: " << filetype << std::endl; out << "Comment: " << comment << std::endl; - return user_write_own (out); + return user_write_own(out); } /***** CAdPlugDatabase::CRecord::CKey *****/ -CAdPlugDatabase::CKey::CKey (binistream & buf) +CAdPlugDatabase::CKey::CKey(binistream &buf) { - make (buf); + make(buf); } -bool -CAdPlugDatabase::CKey::operator== (const CKey & key) +bool CAdPlugDatabase::CKey::operator==(const CKey &key) { return ((crc16 == key.crc16) && (crc32 == key.crc32)); } -void -CAdPlugDatabase::CKey::make (binistream & buf) +void CAdPlugDatabase::CKey::make(binistream &buf) // Key is CRC16:CRC32 pair. CRC16 and CRC32 calculation routines (c) Zhengxi { - static const unsigned short - magic16 = 0xa001; - static const unsigned long - magic32 = 0xedb88320; + static const unsigned short magic16 = 0xa001; + static const unsigned long magic32 = 0xedb88320; - crc16 = 0; - crc32 = ~0; + crc16 = 0; crc32 = ~0; - while (!buf.eof ()) - { - unsigned char - byte = buf.readInt (1); - - for (int j = 0; j < 8; j++) + while(!buf.eof()) { - if ((crc16 ^ byte) & 1) - crc16 = (crc16 >> 1) ^ magic16; - else - crc16 >>= 1; - - if ((crc32 ^ byte) & 1) - crc32 = (crc32 >> 1) ^ magic32; - else - crc32 >>= 1; - - byte >>= 1; + unsigned char byte = buf.readInt(1); + + for (int j=0;j<8;j++) + { + if ((crc16 ^ byte) & 1) + crc16 = (crc16 >> 1) ^ magic16; + else + crc16 >>= 1; + + if ((crc32 ^ byte) & 1) + crc32 = (crc32 >> 1) ^ magic32; + else + crc32 >>= 1; + + byte >>= 1; + } } - } crc16 &= 0xffff; - crc32 = ~crc32; + crc32 = ~crc32; } /***** CInfoRecord *****/ -CInfoRecord::CInfoRecord () +CInfoRecord::CInfoRecord() { type = SongInfo; } -void -CInfoRecord::read_own (binistream & in) +void CInfoRecord::read_own(binistream &in) { - title = in.readString ('\0'); - author = in.readString ('\0'); + title = in.readString('\0'); + author = in.readString('\0'); } -void -CInfoRecord::write_own (binostream & out) +void CInfoRecord::write_own(binostream &out) { - out.writeString (title); - out.writeInt ('\0', 1); - out.writeString (author); - out.writeInt ('\0', 1); + out.writeString(title); out.writeInt('\0', 1); + out.writeString(author); out.writeInt('\0', 1); } -unsigned long -CInfoRecord::get_size () +unsigned long CInfoRecord::get_size() { - return title.length () + author.length () + 2; + return title.length() + author.length() + 2; } -bool -CInfoRecord::user_read_own (std::istream & in, std::ostream & out) +bool CInfoRecord::user_read_own(std::istream &in, std::ostream &out) { - out << "Title: "; - in >> title; - out << "Author: "; - in >> author; + out << "Title: "; in >> title; + out << "Author: "; in >> author; return true; } -bool -CInfoRecord::user_write_own (std::ostream & out) +bool CInfoRecord::user_write_own(std::ostream &out) { out << "Title: " << title << std::endl; out << "Author: " << author << std::endl; @@ -481,39 +392,34 @@ CInfoRecord::user_write_own (std::ostream & out) /***** CClockRecord *****/ -CClockRecord::CClockRecord ():clock (0.0f) +CClockRecord::CClockRecord() + : clock(0.0f) { type = ClockSpeed; } -void -CClockRecord::read_own (binistream & in) +void CClockRecord::read_own(binistream &in) { - clock = in.readFloat (binio::Single); + clock = in.readFloat(binio::Single); } -void -CClockRecord::write_own (binostream & out) +void CClockRecord::write_own(binostream &out) { - out.writeFloat (clock, binio::Single); + out.writeFloat(clock, binio::Single); } -unsigned long -CClockRecord::get_size () +unsigned long CClockRecord::get_size() { return 4; } -bool -CClockRecord::user_read_own (std::istream & in, std::ostream & out) +bool CClockRecord::user_read_own(std::istream &in, std::ostream &out) { - out << "Clockspeed: "; - in >> clock; + out << "Clockspeed: "; in >> clock; return true; } -bool -CClockRecord::user_write_own (std::ostream & out) +bool CClockRecord::user_write_own(std::ostream &out) { out << "Clock speed: " << clock << " Hz" << std::endl; return true; diff --git a/src/adplug/core/database.h b/src/adplug/core/database.h index 859f911..e7e03ee 100644 --- a/src/adplug/core/database.h +++ b/src/adplug/core/database.h @@ -1,17 +1,17 @@ /* * AdPlug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (c) 1999 - 2003 Simon Peter <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -26,8 +26,7 @@ #include <iostream> #include <string> - -#include "binio_virtual.h" +#include "binio.h" class CAdPlugDatabase { @@ -35,8 +34,8 @@ public: class CKey { public: - unsigned short crc16; - unsigned long crc32; + unsigned short crc16; + unsigned long crc32; CKey() {}; CKey(binistream &in); @@ -52,9 +51,9 @@ public: public: typedef enum { Plain, SongInfo, ClockSpeed } RecordType; - RecordType type; - CKey key; - std::string filetype, comment; + RecordType type; + CKey key; + std::string filetype, comment; static CRecord *factory(RecordType type); static CRecord *factory(binistream &in); @@ -78,26 +77,26 @@ public: CAdPlugDatabase(); ~CAdPlugDatabase(); - bool load(std::string db_name); - bool load(binistream &f); - bool save(std::string db_name); - bool save(binostream &f); + bool load(std::string db_name); + bool load(binistream &f); + bool save(std::string db_name); + bool save(binostream &f); - bool insert(CRecord *record); + bool insert(CRecord *record); - void wipe(CRecord *record); - void wipe(); + void wipe(CRecord *record); + void wipe(); CRecord *search(CKey const &key); bool lookup(CKey const &key); CRecord *get_record(); - bool go_forward(); - bool go_backward(); + bool go_forward(); + bool go_backward(); - void goto_begin(); - void goto_end(); + void goto_begin(); + void goto_end(); private: static const unsigned short hash_radix; @@ -105,20 +104,20 @@ private: class DB_Bucket { public: - unsigned long index; - bool deleted; - DB_Bucket *chain; + unsigned long index; + bool deleted; + DB_Bucket *chain; - CRecord *record; + CRecord *record; DB_Bucket(unsigned long nindex, CRecord *newrecord, DB_Bucket *newchain = 0); ~DB_Bucket(); }; - DB_Bucket **db_linear; - DB_Bucket **db_hashed; + DB_Bucket **db_linear; + DB_Bucket **db_hashed; - unsigned long linear_index, linear_logic_length, linear_length; + unsigned long linear_index, linear_logic_length, linear_length; unsigned long make_hash(CKey const &key); }; @@ -139,8 +138,8 @@ protected: class CInfoRecord: public CAdPlugDatabase::CRecord { public: - std::string title; - std::string author; + std::string title; + std::string author; CInfoRecord(); @@ -155,7 +154,7 @@ protected: class CClockRecord: public CAdPlugDatabase::CRecord { public: - float clock; + float clock; CClockRecord(); diff --git a/src/adplug/core/debug.cc b/src/adplug/core/debug.cc index e49b137..59d1f41 100644 --- a/src/adplug/core/debug.cc +++ b/src/adplug/core/debug.cc @@ -26,7 +26,7 @@ #include <stdio.h> #include <stdarg.h> -static FILE *log = nullptr; +static FILE *log = NULL; void AdPlug_LogFile(const char *filename) { diff --git a/src/adplug/core/debug.h b/src/adplug/core/debug.h index 0abd933..2f03efa 100644 --- a/src/adplug/core/debug.h +++ b/src/adplug/core/debug.h @@ -32,8 +32,6 @@ #ifndef H_DEBUG #define H_DEBUG -#define ADL_DEBUG - void AdPlug_LogFile(const char *filename); void AdPlug_LogWrite(const char *fmt, ...); diff --git a/src/adplug/core/dfm.cc b/src/adplug/core/dfm.cc index cb00aa5..d33f158 100644 --- a/src/adplug/core/dfm.cc +++ b/src/adplug/core/dfm.cc @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -25,90 +25,70 @@ #include "dfm.h" #include "debug.h" -CPlayer * -CdfmLoader::factory (Copl * newopl) +CPlayer *CdfmLoader::factory(Copl *newopl) { - return new CdfmLoader (newopl); + return new CdfmLoader(newopl); } -bool -CdfmLoader::load (VFSFile & fd, const CFileProvider & fp) +bool CdfmLoader::load(const std::string &filename, const CFileProvider &fp) { - binistream *f = fp.open (fd); - if (!f) - return false; - unsigned char npats, n, note, fx, c, r, param; - unsigned int i; - const unsigned char convfx[8] = { 255, 255, 17, 19, 23, 24, 255, 13 }; + binistream *f = fp.open(filename); if(!f) return false; + unsigned char npats,n,note,fx,c,r,param; + unsigned int i; + const unsigned char convfx[8] = {255,255,17,19,23,24,255,13}; // file validation - f->readString (header.id, 4); - header.hiver = f->readInt (1); - header.lover = f->readInt (1); - if (strncmp (header.id, "DFM\x1a", 4) || header.hiver > 1) - { - fp.close (f); - return false; - } + f->readString(header.id, 4); + header.hiver = f->readInt(1); header.lover = f->readInt(1); + if(strncmp(header.id,"DFM\x1a",4) || header.hiver > 1) + { fp.close(f); return false; } // load - restartpos = 0; - flags = Standard; - bpm = 0; - init_trackord (); - f->readString (songinfo, 33); - initspeed = f->readInt (1); - for (i = 0; i < 32; i++) - f->readString (instname[i], 12); - for (i = 0; i < 32; i++) - { - inst[i].data[1] = f->readInt (1); - inst[i].data[2] = f->readInt (1); - inst[i].data[9] = f->readInt (1); - inst[i].data[10] = f->readInt (1); - inst[i].data[3] = f->readInt (1); - inst[i].data[4] = f->readInt (1); - inst[i].data[5] = f->readInt (1); - inst[i].data[6] = f->readInt (1); - inst[i].data[7] = f->readInt (1); - inst[i].data[8] = f->readInt (1); - inst[i].data[0] = f->readInt (1); + restartpos = 0; flags = Standard; bpm = 0; + init_trackord(); + f->readString(songinfo, 33); + initspeed = f->readInt(1); + for(i = 0; i < 32; i++) + f->readString(instname[i], 12); + for(i = 0; i < 32; i++) { + inst[i].data[1] = f->readInt(1); + inst[i].data[2] = f->readInt(1); + inst[i].data[9] = f->readInt(1); + inst[i].data[10] = f->readInt(1); + inst[i].data[3] = f->readInt(1); + inst[i].data[4] = f->readInt(1); + inst[i].data[5] = f->readInt(1); + inst[i].data[6] = f->readInt(1); + inst[i].data[7] = f->readInt(1); + inst[i].data[8] = f->readInt(1); + inst[i].data[0] = f->readInt(1); } - for (i = 0; i < 128; i++) - order[i] = f->readInt (1); - for (i = 0; i < 128 && order[i] != 128; i++); - length = i; - npats = f->readInt (1); - for (i = 0; i < npats; i++) - { - n = f->readInt (1); - for (r = 0; r < 64; r++) - for (c = 0; c < 9; c++) - { - note = f->readInt (1); - if ((note & 15) == 15) - tracks[n * 9 + c][r].note = 127; // key off + for(i = 0; i < 128; i++) order[i] = f->readInt(1); + for(i = 0; i < 128 && order[i] != 128; i++) continue; length = i; + npats = f->readInt(1); + for(i = 0; i < npats; i++) { + n = f->readInt(1); + for(r = 0; r < 64; r++) + for(c = 0; c < 9; c++) { + note = f->readInt(1); + if((note & 15) == 15) + tracks[n*9+c][r].note = 127; // key off else - tracks[n * 9 + c][r].note = ((note & 127) >> 4) * 12 + (note & 15); - if (note & 128) - { // additional effect byte - fx = f->readInt (1); - if (fx >> 5 == 1) - tracks[n * 9 + c][r].inst = (fx & 31) + 1; - else - { - tracks[n * 9 + c][r].command = convfx[fx >> 5]; - if (tracks[n * 9 + c][r].command == 17) - { // set volume + tracks[n*9+c][r].note = ((note & 127) >> 4) * 12 + (note & 15); + if(note & 128) { // additional effect byte + fx = f->readInt(1); + if(fx >> 5 == 1) + tracks[n*9+c][r].inst = (fx & 31) + 1; + else { + tracks[n*9+c][r].command = convfx[fx >> 5]; + if(tracks[n*9+c][r].command == 17) { // set volume param = fx & 31; param = 63 - param * 2; - tracks[n * 9 + c][r].param1 = param >> 4; - tracks[n * 9 + c][r].param2 = param & 15; - } - else - { - tracks[n * 9 + c][r].param1 = (fx & 31) >> 4; - tracks[n * 9 + c][r].param2 = fx & 15; + tracks[n*9+c][r].param1 = param >> 4; + tracks[n*9+c][r].param2 = param & 15; + } else { + tracks[n*9+c][r].param1 = (fx & 31) >> 4; + tracks[n*9+c][r].param2 = fx & 15; } } } @@ -116,22 +96,20 @@ CdfmLoader::load (VFSFile & fd, const CFileProvider & fp) } } - fp.close (f); - rewind (0); + fp.close(f); + rewind(0); return true; } -std::string CdfmLoader::gettype () +std::string CdfmLoader::gettype() { - char - tmpstr[20]; + char tmpstr[20]; - sprintf (tmpstr, "Digital-FM %d.%d", header.hiver, header.lover); - return std::string (tmpstr); + sprintf(tmpstr,"Digital-FM %d.%d",header.hiver,header.lover); + return std::string(tmpstr); } -float -CdfmLoader::getrefresh () +float CdfmLoader::getrefresh() { - return 125.0f; + return 125.0f; } diff --git a/src/adplug/core/dfm.h b/src/adplug/core/dfm.h index 0d7770e..fa46833 100644 --- a/src/adplug/core/dfm.h +++ b/src/adplug/core/dfm.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -26,27 +26,27 @@ class CdfmLoader: public CmodPlayer public: static CPlayer *factory(Copl *newopl); - CdfmLoader(Copl *newopl) - : CmodPlayer(newopl) - { }; + CdfmLoader(Copl *newopl) + : CmodPlayer(newopl) + { }; - bool load(VFSFile &fd, const CFileProvider &fp); - float getrefresh(); + bool load(const std::string &filename, const CFileProvider &fp); + float getrefresh(); - std::string gettype(); - unsigned int getinstruments() - { return 32; }; - std::string getinstrument(unsigned int n) - { if(*instname[n]) return std::string(instname[n],1,*instname[n]); else return std::string(); }; - std::string getdesc() - { return std::string(songinfo,1,*songinfo); }; + std::string gettype(); + unsigned int getinstruments() + { return 32; }; + std::string getinstrument(unsigned int n) + { if(*instname[n]) return std::string(instname[n],1,*instname[n]); else return std::string(); }; + std::string getdesc() + { return std::string(songinfo,1,*songinfo); }; private: - struct { - char id[4]; - unsigned char hiver,lover; - } header; + struct { + char id[4]; + unsigned char hiver,lover; + } header; - char songinfo[33]; - char instname[32][12]; + char songinfo[33]; + char instname[32][12]; }; diff --git a/src/adplug/core/diskopl.h b/src/adplug/core/diskopl.h deleted file mode 100644 index 9bc41d7..0000000 --- a/src/adplug/core/diskopl.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Adplug - Replayer for many OPL2/OPL3 audio file formats. - * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al. - * - * 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; either - * version 2.1 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 - * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * diskopl.h - Disk Writer OPL, by Simon Peter <dn.tlp@gmx.net> - */ - -#include <string> -#include <stdio.h> -#include "opl.h" -#include "player.h" - -class CDiskopl: public Copl -{ - public: - CDiskopl(std::string filename); - virtual ~CDiskopl(); - - void update(CPlayer *p); // write to file - void setnowrite(bool nw = true) // set file write status - { nowrite = nw; }; - - void setchip(int n); - - // template methods - void write(int reg, int val); - void init(); - - private: - static const unsigned char op_table[9]; - - FILE *f; - float old_freq; - unsigned char del; - bool nowrite; // don't write to file, if true - - void diskwrite(int reg, int val); -}; diff --git a/src/adplug/core/dmo.cc b/src/adplug/core/dmo.cc index bf9d222..72c0450 100644 --- a/src/adplug/core/dmo.cc +++ b/src/adplug/core/dmo.cc @@ -26,7 +26,7 @@ */ #include <string.h> -#include <binstr.h> +#include "binstr.h" #include "dmo.h" #include "debug.h" @@ -38,160 +38,152 @@ #define ARRAY_AS_DWORD(a, i) \ ((a[i + 3] << 24) + (a[i + 2] << 16) + (a[i + 1] << 8) + a[i]) -#define ARRAY_AS_WORD(a, i) ((a[i + 1] << 8) + a[i]) +#define ARRAY_AS_WORD(a, i) ((a[i + 1] << 8) + a[i]) -#define CHARP_AS_WORD(p) (((*(p + 1)) << 8) + (*p)) +#define CHARP_AS_WORD(p) (((*(p + 1)) << 8) + (*p)) /* -------- Public Methods -------------------------------- */ -CPlayer * -CdmoLoader::factory (Copl * newopl) +CPlayer *CdmoLoader::factory(Copl *newopl) { - return new CdmoLoader (newopl); + return new CdmoLoader(newopl); } -bool -CdmoLoader::load (VFSFile & fd, const CFileProvider & fp) +bool CdmoLoader::load(const std::string &filename, const CFileProvider &fp) { - int i, j; + int i,j; binistream *f; - std::string filename (fd.filename ()); // check header dmo_unpacker *unpacker = new dmo_unpacker; unsigned char chkhdr[16]; - f = fp.open (fd); + if (!fp.extension(filename, ".dmo")) + { + delete unpacker; + return false; + } + + f = fp.open(filename); if (!f) - { - delete unpacker; - return false; - } - if (!fp.extension (filename, ".dmo")) - { - delete unpacker; - return false; - } + { + delete unpacker; + return false; + } - f->readString ((char *) chkhdr, 16); + f->readString((char *)chkhdr, 16); - if (!unpacker->decrypt (chkhdr, 16)) - { - delete unpacker; - fp.close (f); - return false; - } + if (!unpacker->decrypt(chkhdr, 16)) + { + delete unpacker; + fp.close(f); + return false; + } // get file size - long packed_length = fp.filesize (f); - f->seek (0); + long packed_length = fp.filesize(f); + f->seek(0); - unsigned char *packed_module = new unsigned char[packed_length]; + unsigned char *packed_module = new unsigned char [packed_length]; // load file - f->readString ((char *) packed_module, packed_length); - fp.close (f); + f->readString((char *)packed_module, packed_length); + fp.close(f); // decrypt - unpacker->decrypt (packed_module, packed_length); + unpacker->decrypt(packed_module,packed_length); - long unpacked_length = 0x2000 * ARRAY_AS_WORD (packed_module, 12); - unsigned char *module = new unsigned char[unpacked_length]; + long unpacked_length = 0x2000 * ARRAY_AS_WORD(packed_module, 12); + unsigned char *module = new unsigned char [unpacked_length]; // unpack - if (!unpacker->unpack (packed_module + 12, module, unpacked_length)) - { - delete unpacker; - delete[]packed_module; - delete[]module; - return false; - } + if (!unpacker->unpack(packed_module+12,module,unpacked_length)) + { + delete unpacker; + delete [] packed_module; + delete [] module; + return false; + } delete unpacker; - delete[]packed_module; + delete [] packed_module; // "TwinTeam" - signed ? - if (memcmp (module, "TwinTeam Module File" "\x0D\x0A", 22)) - { - delete module; - return false; - } + if (memcmp(module,"TwinTeam Module File""\x0D\x0A",22)) + { + delete [] module; + return false; + } // load header - binisstream uf (module, unpacked_length); - uf.setFlag (binio::BigEndian, false); - uf.setFlag (binio::FloatIEEE); + binisstream uf(module, unpacked_length); + uf.setFlag(binio::BigEndian, false); uf.setFlag(binio::FloatIEEE); - memset (&header, 0, sizeof (s3mheader)); + memset(&header,0,sizeof(s3mheader)); - uf.ignore (22); // ignore DMO header ID string - uf.readString (header.name, 28); + uf.ignore(22); // ignore DMO header ID string + uf.readString(header.name, 28); - uf.ignore (2); // _unk_1 - header.ordnum = uf.readInt (2); - header.insnum = uf.readInt (2); - header.patnum = uf.readInt (2); - uf.ignore (2); // _unk_2 - header.is = uf.readInt (2); - header.it = uf.readInt (2); + uf.ignore(2); // _unk_1 + header.ordnum = uf.readInt(2); + header.insnum = uf.readInt(2); + header.patnum = uf.readInt(2); + uf.ignore(2); // _unk_2 + header.is = uf.readInt(2); + header.it = uf.readInt(2); - memset (header.chanset, 0xFF, 32); + memset(header.chanset,0xFF,32); - for (i = 0; i < 9; i++) + for (i=0;i<9;i++) header.chanset[i] = 0x10 + i; - uf.ignore (32); // ignore panning settings for all 32 channels + uf.ignore(32); // ignore panning settings for all 32 channels // load orders - for (i = 0; i < 256; i++) - orders[i] = uf.readInt (1); + for(i = 0; i < 256; i++) orders[i] = uf.readInt(1); orders[header.ordnum] = 0xFF; // load pattern lengths unsigned short my_patlen[100]; - for (i = 0; i < 100; i++) - my_patlen[i] = uf.readInt (2); + for(i = 0; i < 100; i++) my_patlen[i] = uf.readInt(2); // load instruments for (i = 0; i < header.insnum; i++) - { - memset (&inst[i], 0, sizeof (s3minst)); - - uf.readString (inst[i].name, 28); - - inst[i].volume = uf.readInt (1); - inst[i].dsk = uf.readInt (1); - inst[i].c2spd = uf.readInt (4); - inst[i].type = uf.readInt (1); - inst[i].d00 = uf.readInt (1); - inst[i].d01 = uf.readInt (1); - inst[i].d02 = uf.readInt (1); - inst[i].d03 = uf.readInt (1); - inst[i].d04 = uf.readInt (1); - inst[i].d05 = uf.readInt (1); - inst[i].d06 = uf.readInt (1); - inst[i].d07 = uf.readInt (1); - inst[i].d08 = uf.readInt (1); - inst[i].d09 = uf.readInt (1); - inst[i].d0a = uf.readInt (1); - /* - * Originally, riven sets d0b = d0a and ignores 1 byte in the - * stream, but i guess this was a typo, so i read it here. - */ - inst[i].d0b = uf.readInt (1); - } + { + memset(&inst[i],0,sizeof(s3minst)); + + uf.readString(inst[i].name, 28); + + inst[i].volume = uf.readInt(1); + inst[i].dsk = uf.readInt(1); + inst[i].c2spd = uf.readInt(4); + inst[i].type = uf.readInt(1); + inst[i].d00 = uf.readInt(1); + inst[i].d01 = uf.readInt(1); + inst[i].d02 = uf.readInt(1); + inst[i].d03 = uf.readInt(1); + inst[i].d04 = uf.readInt(1); + inst[i].d05 = uf.readInt(1); + inst[i].d06 = uf.readInt(1); + inst[i].d07 = uf.readInt(1); + inst[i].d08 = uf.readInt(1); + inst[i].d09 = uf.readInt(1); + inst[i].d0a = uf.readInt(1); + /* + * Originally, riven sets d0b = d0a and ignores 1 byte in the + * stream, but i guess this was a typo, so i read it here. + */ + inst[i].d0b = uf.readInt(1); + } // load patterns - for (i = 0; i < header.patnum; i++) - { - long cur_pos = uf.pos (); + for (i = 0; i < header.patnum; i++) { + long cur_pos = uf.pos(); - for (j = 0; j < 64; j++) - { - while (1) - { - unsigned char token = uf.readInt (1); + for (j = 0; j < 64; j++) { + while (1) { + unsigned char token = uf.readInt(1); if (!token) break; @@ -199,258 +191,229 @@ CdmoLoader::load (VFSFile & fd, const CFileProvider & fp) unsigned char chan = token & 31; // note + instrument ? - if (token & 32) - { - unsigned char bufbyte = uf.readInt (1); + if (token & 32) { + unsigned char bufbyte = uf.readInt(1); pattern[i][j][chan].note = bufbyte & 15; pattern[i][j][chan].oct = bufbyte >> 4; - pattern[i][j][chan].instrument = uf.readInt (1); + pattern[i][j][chan].instrument = uf.readInt(1); } // volume ? if (token & 64) - pattern[i][j][chan].volume = uf.readInt (1); + pattern[i][j][chan].volume = uf.readInt(1); // command ? - if (token & 128) - { - pattern[i][j][chan].command = uf.readInt (1); - pattern[i][j][chan].info = uf.readInt (1); + if (token & 128) { + pattern[i][j][chan].command = uf.readInt(1); + pattern[i][j][chan].info = uf.readInt(1); } } } - uf.seek (cur_pos + my_patlen[i]); + uf.seek(cur_pos + my_patlen[i]); } - delete[]module; - rewind (0); + delete [] module; + rewind(0); return true; } -std::string CdmoLoader::gettype () +std::string CdmoLoader::gettype() { - return std::string ("TwinTeam (packed S3M)"); + return std::string("TwinTeam (packed S3M)"); } -std::string CdmoLoader::getauthor () +std::string CdmoLoader::getauthor() { /* - All available .DMO modules written by one composer. And because all .DMO - stuff was lost due to hd crash (TwinTeam guys said this), there are - never(?) be another. - */ - return std::string ("Benjamin GERARDIN"); + All available .DMO modules written by one composer. And because all .DMO + stuff was lost due to hd crash (TwinTeam guys said this), there are + never(?) be another. + */ + return std::string("Benjamin GERARDIN"); } /* -------- Private Methods ------------------------------- */ -unsigned short -CdmoLoader::dmo_unpacker::brand (unsigned short range) +unsigned short CdmoLoader::dmo_unpacker::brand(unsigned short range) { - unsigned short - ax, - bx, - cx, - dx; - - ax = LOWORD (bseed); - bx = HIWORD (bseed); + unsigned short ax,bx,cx,dx; + + ax = LOWORD(bseed); + bx = HIWORD(bseed); cx = ax; - ax = LOWORD (cx * 0x8405); - dx = HIWORD (cx * 0x8405); + ax = LOWORD(cx * 0x8405); + dx = HIWORD(cx * 0x8405); cx <<= 3; - cx = (((HIBYTE (cx) + LOBYTE (cx)) & 0xFF) << 8) + LOBYTE (cx); + cx = (((HIBYTE(cx) + LOBYTE(cx)) & 0xFF) << 8) + LOBYTE(cx); dx += cx; dx += bx; bx <<= 2; dx += bx; - dx = (((HIBYTE (dx) + LOBYTE (bx)) & 0xFF) << 8) + LOBYTE (dx); + dx = (((HIBYTE(dx) + LOBYTE(bx)) & 0xFF) << 8) + LOBYTE(dx); bx <<= 5; - dx = (((HIBYTE (dx) + LOBYTE (bx)) & 0xFF) << 8) + LOBYTE (dx); + dx = (((HIBYTE(dx) + LOBYTE(bx)) & 0xFF) << 8) + LOBYTE(dx); ax += 1; - if (!ax) - dx += 1; + if (!ax) dx += 1; // leave it that way or amd64 might get it wrong bseed = dx; bseed <<= 16; bseed += ax; - return HIWORD (HIWORD (LOWORD (bseed) * range) + HIWORD (bseed) * range); + return HIWORD(HIWORD(LOWORD(bseed) * range) + HIWORD(bseed) * range); } -bool -CdmoLoader::dmo_unpacker::decrypt (unsigned char *buf, long len) +bool CdmoLoader::dmo_unpacker::decrypt(unsigned char *buf, long len) { - unsigned long - seed = 0; - int - i; + unsigned long seed = 0; + int i; - bseed = ARRAY_AS_DWORD (buf, 0); + bseed = ARRAY_AS_DWORD(buf, 0); - for (i = 0; i < ARRAY_AS_WORD (buf, 4) + 1; i++) - seed += brand (0xffff); + for (i=0; i < ARRAY_AS_WORD(buf, 4) + 1; i++) + seed += brand(0xffff); - bseed = seed ^ ARRAY_AS_DWORD (buf, 6); + bseed = seed ^ ARRAY_AS_DWORD(buf, 6); - if (ARRAY_AS_WORD (buf, 10) != brand (0xffff)) + if (ARRAY_AS_WORD(buf, 10) != brand(0xffff)) return false; - for (i = 0; i < (len - 12); i++) - buf[12 + i] ^= brand (0x100); + for (i=0;i<(len-12);i++) + buf[12+i] ^= brand(0x100); buf[len - 2] = buf[len - 1] = 0; return true; } -short -CdmoLoader::dmo_unpacker::unpack_block (unsigned char *ibuf, long ilen, - unsigned char *obuf) +short CdmoLoader::dmo_unpacker::unpack_block(unsigned char *ibuf, long ilen, unsigned char *obuf) { - unsigned char - code, - par1, - par2; - unsigned short - ax, - bx, - cx; - - unsigned char * - ipos = ibuf; - unsigned char * - opos = obuf; + unsigned char code,par1,par2; + unsigned short ax,bx,cx; + + unsigned char *ipos = ibuf; + unsigned char *opos = obuf; // LZ77 child while (ipos - ibuf < ilen) - { - code = *ipos++; - - // 00xxxxxx: copy (xxxxxx + 1) bytes - if ((code >> 6) == 0) { - cx = (code & 0x3F) + 1; + code = *ipos++; - if (opos + cx >= oend) - return -1; + // 00xxxxxx: copy (xxxxxx + 1) bytes + if ((code >> 6) == 0) + { + cx = (code & 0x3F) + 1; - for (int i = 0; i < cx; i++) - *opos++ = *ipos++; + if(opos + cx >= oend) + return -1; - continue; - } + for (int i=0;i<cx;i++) + *opos++ = *ipos++; - // 01xxxxxx xxxyyyyy: copy (Y + 3) bytes from (X + 1) - if ((code >> 6) == 1) - { - par1 = *ipos++; + continue; + } - ax = ((code & 0x3F) << 3) + ((par1 & 0xE0) >> 5) + 1; - cx = (par1 & 0x1F) + 3; + // 01xxxxxx xxxyyyyy: copy (Y + 3) bytes from (X + 1) + if ((code >> 6) == 1) + { + par1 = *ipos++; - if (opos + cx >= oend) - return -1; + ax = ((code & 0x3F) << 3) + ((par1 & 0xE0) >> 5) + 1; + cx = (par1 & 0x1F) + 3; - for (int i = 0; i < cx; i++) { - *opos = *(opos - ax); - opos++; - } + if(opos + cx >= oend) + return -1; - continue; - } + for(int i=0;i<cx;i++) { + *opos = *(opos - ax); + opos++; + } - // 10xxxxxx xyyyzzzz: copy (Y + 3) bytes from (X + 1); copy Z bytes - if ((code >> 6) == 2) - { - int - i; + continue; + } - par1 = *ipos++; + // 10xxxxxx xyyyzzzz: copy (Y + 3) bytes from (X + 1); copy Z bytes + if ((code >> 6) == 2) + { + int i; - ax = ((code & 0x3F) << 1) + (par1 >> 7) + 1; - cx = ((par1 & 0x70) >> 4) + 3; - bx = par1 & 0x0F; + par1 = *ipos++; - if (opos + bx + cx >= oend) - return -1; + ax = ((code & 0x3F) << 1) + (par1 >> 7) + 1; + cx = ((par1 & 0x70) >> 4) + 3; + bx = par1 & 0x0F; - for (i = 0; i < cx; i++) { - *opos = *(opos - ax); - opos++; - } + if(opos + bx + cx >= oend) + return -1; - for (i = 0; i < bx; i++) - *opos++ = *ipos++; + for(i=0;i<cx;i++) { + *opos = *(opos - ax); + opos++; + } - continue; - } + for (i=0;i<bx;i++) + *opos++ = *ipos++; - // 11xxxxxx xxxxxxxy yyyyzzzz: copy (Y + 4) from X; copy Z bytes - if ((code >> 6) == 3) - { - int - i; + continue; + } - par1 = *ipos++; - par2 = *ipos++; + // 11xxxxxx xxxxxxxy yyyyzzzz: copy (Y + 4) from X; copy Z bytes + if ((code >> 6) == 3) + { + int i; - bx = ((code & 0x3F) << 7) + (par1 >> 1); - cx = ((par1 & 0x01) << 4) + (par2 >> 4) + 4; - ax = par2 & 0x0F; + par1 = *ipos++; + par2 = *ipos++; - if (opos + ax + cx >= oend) - return -1; + bx = ((code & 0x3F) << 7) + (par1 >> 1); + cx = ((par1 & 0x01) << 4) + (par2 >> 4) + 4; + ax = par2 & 0x0F; - for (i = 0; i < cx; i++) { - *opos = *(opos - bx); - opos++; - } + if(opos + ax + cx >= oend) + return -1; - for (i = 0; i < ax; i++) - *opos++ = *ipos++; + for(i=0;i<cx;i++) { + *opos = *(opos - bx); + opos++; + } - continue; + for (i=0;i<ax;i++) + *opos++ = *ipos++; + + continue; + } } - } return opos - obuf; } -long -CdmoLoader::dmo_unpacker::unpack (unsigned char *ibuf, unsigned char *obuf, - unsigned long outputsize) +long CdmoLoader::dmo_unpacker::unpack(unsigned char *ibuf, unsigned char *obuf, + unsigned long outputsize) { - long - olen = 0; - unsigned short - block_count = CHARP_AS_WORD (ibuf); + long olen = 0; + unsigned short block_count = CHARP_AS_WORD(ibuf); ibuf += 2; - unsigned char * - block_length = ibuf; + unsigned char *block_length = ibuf; ibuf += 2 * block_count; oend = obuf + outputsize; - for (int i = 0; i < block_count; i++) - { - unsigned short - bul = CHARP_AS_WORD (ibuf); + for (int i=0;i<block_count;i++) + { + unsigned short bul = CHARP_AS_WORD(ibuf); - if (unpack_block (ibuf + 2, CHARP_AS_WORD (block_length) - 2, obuf) != - bul) - return 0; + if(unpack_block(ibuf + 2,CHARP_AS_WORD(block_length) - 2,obuf) != bul) + return 0; - obuf += bul; - olen += bul; + obuf += bul; + olen += bul; - ibuf += CHARP_AS_WORD (block_length); - block_length += 2; - } + ibuf += CHARP_AS_WORD(block_length); + block_length += 2; + } return olen; } diff --git a/src/adplug/core/dmo.h b/src/adplug/core/dmo.h index 2ae068f..63b6b85 100644 --- a/src/adplug/core/dmo.h +++ b/src/adplug/core/dmo.h @@ -28,10 +28,10 @@ class CdmoLoader: public Cs3mPlayer CdmoLoader(Copl *newopl) : Cs3mPlayer(newopl) { }; - bool load(VFSFile &fd, const CFileProvider &fp); + bool load(const std::string &filename, const CFileProvider &fp); - std::string gettype(); - std::string getauthor(); + std::string gettype(); + std::string getauthor(); private: @@ -39,7 +39,7 @@ class CdmoLoader: public Cs3mPlayer public: bool decrypt(unsigned char *buf, long len); long unpack(unsigned char *ibuf, unsigned char *obuf, - unsigned long outputsize); + unsigned long outputsize); private: unsigned short brand(unsigned short range); diff --git a/src/adplug/core/dro.cc b/src/adplug/core/dro.cc index f93bb2c..179ddf3 100644 --- a/src/adplug/core/dro.cc +++ b/src/adplug/core/dro.cc @@ -23,129 +23,119 @@ * NOTES: 3-oct-04: the DRO format is not yet finalized. beware. */ +#include <cstring> #include <stdio.h> -#include <string.h> #include "dro.h" /*** public methods *************************************/ -CPlayer * -CdroPlayer::factory (Copl * newopl) +CPlayer *CdroPlayer::factory(Copl *newopl) { - return new CdroPlayer (newopl); + return new CdroPlayer(newopl); } -CdroPlayer::CdroPlayer (Copl * newopl):CPlayer (newopl), data (0) +CdroPlayer::CdroPlayer(Copl *newopl) + : CPlayer(newopl), data(0) { - if (opl->gettype () == Copl::TYPE_OPL2) + if(opl->gettype() == Copl::TYPE_OPL2) opl3_mode = 0; else opl3_mode = 1; } -bool -CdroPlayer::load (VFSFile & fd, const CFileProvider & fp) +bool CdroPlayer::load(const std::string &filename, const CFileProvider &fp) { - binistream *f = fp.open (fd); - if (!f) - return false; + binistream *f = fp.open(filename); if(!f) return false; char id[8]; unsigned long i; // file validation section - f->readString (id, 8); - if (strncmp (id, "DBRAWOPL", 8)) - { - fp.close (f); - return false; - } - int version = f->readInt (4); // not very useful just yet - if (version != 0x10000) - { - fp.close (f); - return false; - } + f->readString(id, 8); + if(strncmp(id,"DBRAWOPL",8)) { fp.close (f); return false; } + int version = f->readInt(4); // not very useful just yet + if(version != 0x10000) { fp.close(f); return false; } // load section - mstotal = f->readInt (4); // Total milliseconds in file - length = f->readInt (4); // Total data bytes in file - f->ignore (4); // Type of opl data this can contain - ignored - data = new unsigned char[length]; - for (i = 0; i < length; i++) - data[i] = f->readInt (1); - fp.close (f); - rewind (0); + mstotal = f->readInt(4); // Total milliseconds in file + length = f->readInt(4); // Total data bytes in file + data = new unsigned char [length]; + + f->ignore(1); // Type of opl data this can contain - ignored + for (i=0;i<3;i++) + data[i]=f->readInt(1); + + if ((data[0] == 0) || (data[1] == 0) || (data[2] == 0)) { + // Some early .DRO files only used one byte for the hardware type, then + // later changed to four bytes with no version number change. If we're + // here then this is a later (more popular) file with the full four bytes + // for the hardware-type. + i = 0; // so ignore the three bytes we just read and start again + } + for (;i<length;i++) + data[i]=f->readInt(1); + fp.close(f); + rewind(0); return true; } -bool -CdroPlayer::update () +bool CdroPlayer::update() { - if (delay > 500) - { - delay -= 500; + if (delay>500) { + delay-=500; return true; - } - else - delay = 0; + } else + delay=0; - while (pos < length) - { + while (pos < length) { unsigned char cmd = data[pos++]; - switch (cmd) - { + switch(cmd) { case 0: delay = 1 + data[pos++]; return true; case 1: - delay = 1 + data[pos] + (data[pos + 1] << 8); - pos += 2; + delay = 1 + data[pos] + (data[pos+1]<<8); + pos+=2; return true; case 2: index = 0; - opl->setchip (0); + opl->setchip(0); break; case 3: index = 1; - opl->setchip (1); + opl->setchip(1); break; default: - if (cmd == 4) - cmd = data[pos++]; //data override - if (index == 0 || opl3_mode) - opl->write (cmd, data[pos++]); + if(cmd==4) cmd = data[pos++]; //data override + if(index == 0 || opl3_mode) + opl->write(cmd,data[pos++]); break; } } - return pos < length; + return pos<length; } -void -CdroPlayer::rewind (int subsong) +void CdroPlayer::rewind(int subsong) { - delay = 1; + delay=1; pos = index = 0; - opl->init (); + opl->init(); //dro assumes all registers are initialized to 0 //registers not initialized to 0 will be corrected //in the data stream - for (int i = 0; i < 256; i++) - opl->write (i, 0); + for(int i=0;i<256;i++) + opl->write(i,0); - opl->setchip (1); - for (int i = 0; i < 256; i++) - opl->write (i, 0); - opl->setchip (0); + opl->setchip(1); + for(int i=0;i<256;i++) + opl->write(i,0); + opl->setchip(0); } -float -CdroPlayer::getrefresh () +float CdroPlayer::getrefresh() { - if (delay > 500) - return 1000 / 500; - else - return 1000 / (double) delay; + if (delay > 500) return 1000 / 500; + else return 1000 / (double)delay; } diff --git a/src/adplug/core/dro.h b/src/adplug/core/dro.h index e1c2bc0..bcc23a6 100644 --- a/src/adplug/core/dro.h +++ b/src/adplug/core/dro.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -30,10 +30,10 @@ class CdroPlayer: public CPlayer ~CdroPlayer() { if(data) - delete [] data; + delete [] data; } - bool load(VFSFile &fd, const CFileProvider &fp); + bool load(const std::string &filename, const CFileProvider &fp); bool update(); void rewind(int subsong); float getrefresh(); diff --git a/src/adplug/core/dro2.cc b/src/adplug/core/dro2.cc index a3aab33..94a5a05 100644 --- a/src/adplug/core/dro2.cc +++ b/src/adplug/core/dro2.cc @@ -30,113 +30,113 @@ CPlayer *Cdro2Player::factory(Copl *newopl) } Cdro2Player::Cdro2Player(Copl *newopl) : - CPlayer(newopl), - piConvTable(nullptr), - data(0) + CPlayer(newopl), + piConvTable(NULL), + data(0) { } Cdro2Player::~Cdro2Player() { - if (this->data) delete[] this->data; - if (this->piConvTable) delete[] this->piConvTable; + if (this->data) delete[] this->data; + if (this->piConvTable) delete[] this->piConvTable; } -bool Cdro2Player::load(VFSFile & fd, const CFileProvider & fp) +bool Cdro2Player::load(const std::string &filename, const CFileProvider &fp) { - binistream *f = fp.open(fd); - if (!f) return false; - - char id[8]; - f->readString(id, 8); - if (strncmp(id, "DBRAWOPL", 8)) { - fp.close(f); - return false; - } - int version = f->readInt(4); - if (version != 0x2) { - fp.close(f); - return false; - } - - this->iLength = f->readInt(4) * 2; // stored in file as number of byte pairs - f->ignore(4); // Length in milliseconds - f->ignore(1); /// OPL type (0 == OPL2, 1 == Dual OPL2, 2 == OPL3) - int iFormat = f->readInt(1); - if (iFormat != 0) { - fp.close(f); - return false; - } - int iCompression = f->readInt(1); - if (iCompression != 0) { - fp.close(f); - return false; - } - this->iCmdDelayS = f->readInt(1); - this->iCmdDelayL = f->readInt(1); - this->iConvTableLen = f->readInt(1); - - this->piConvTable = new uint8_t[this->iConvTableLen]; - f->readString((char *)this->piConvTable, this->iConvTableLen); - - this->data = new uint8_t[this->iLength]; - f->readString((char *)this->data, this->iLength); - - fp.close(f); - rewind(0); - - return true; + binistream *f = fp.open(filename); + if (!f) return false; + + char id[8]; + f->readString(id, 8); + if (strncmp(id, "DBRAWOPL", 8)) { + fp.close(f); + return false; + } + int version = f->readInt(4); + if (version != 0x2) { + fp.close(f); + return false; + } + + this->iLength = f->readInt(4) * 2; // stored in file as number of byte pairs + f->ignore(4); // Length in milliseconds + f->ignore(1); /// OPL type (0 == OPL2, 1 == Dual OPL2, 2 == OPL3) + int iFormat = f->readInt(1); + if (iFormat != 0) { + fp.close(f); + return false; + } + int iCompression = f->readInt(1); + if (iCompression != 0) { + fp.close(f); + return false; + } + this->iCmdDelayS = f->readInt(1); + this->iCmdDelayL = f->readInt(1); + this->iConvTableLen = f->readInt(1); + + this->piConvTable = new uint8_t[this->iConvTableLen]; + f->readString((char *)this->piConvTable, this->iConvTableLen); + + this->data = new uint8_t[this->iLength]; + f->readString((char *)this->data, this->iLength); + + fp.close(f); + rewind(0); + + return true; } bool Cdro2Player::update() { - while (this->iPos < this->iLength) { - int iIndex = this->data[this->iPos++]; - int iValue = this->data[this->iPos++]; - - // Short delay - if (iIndex == this->iCmdDelayS) { - this->iDelay = iValue + 1; - return true; - - // Long delay - } else if (iIndex == this->iCmdDelayL) { - this->iDelay = (iValue + 1) << 8; - return true; - - // Normal write - } else { - if (iIndex & 0x80) { - // High bit means use second chip in dual-OPL2 config - this->opl->setchip(1); - iIndex &= 0x7F; - } else { - this->opl->setchip(0); - } - if (iIndex > this->iConvTableLen) { - printf("DRO2: Error - index beyond end of codemap table! Corrupted .dro?\n"); - return false; // EOF - } - int iReg = this->piConvTable[iIndex]; - this->opl->write(iReg, iValue); - } - - } - - // This won't result in endless-play using Adplay, but IMHO that code belongs - // in Adplay itself, not here. + while (this->iPos < this->iLength) { + int iIndex = this->data[this->iPos++]; + int iValue = this->data[this->iPos++]; + + // Short delay + if (iIndex == this->iCmdDelayS) { + this->iDelay = iValue + 1; + return true; + + // Long delay + } else if (iIndex == this->iCmdDelayL) { + this->iDelay = (iValue + 1) << 8; + return true; + + // Normal write + } else { + if (iIndex & 0x80) { + // High bit means use second chip in dual-OPL2 config + this->opl->setchip(1); + iIndex &= 0x7F; + } else { + this->opl->setchip(0); + } + if (iIndex > this->iConvTableLen) { + printf("DRO2: Error - index beyond end of codemap table! Corrupted .dro?\n"); + return false; // EOF + } + int iReg = this->piConvTable[iIndex]; + this->opl->write(iReg, iValue); + } + + } + + // This won't result in endless-play using Adplay, but IMHO that code belongs + // in Adplay itself, not here. return this->iPos < this->iLength; } void Cdro2Player::rewind(int subsong) { - this->iDelay = 0; - this->iPos = 0; + this->iDelay = 0; + this->iPos = 0; opl->init(); } float Cdro2Player::getrefresh() { - if (this->iDelay > 0) return 1000.0 / this->iDelay; - else return 1000.0; + if (this->iDelay > 0) return 1000.0 / this->iDelay; + else return 1000.0; } diff --git a/src/adplug/core/dro2.h b/src/adplug/core/dro2.h index 1a89310..a7b3d33 100644 --- a/src/adplug/core/dro2.h +++ b/src/adplug/core/dro2.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -24,37 +24,37 @@ class Cdro2Player: public CPlayer { - protected: - uint8_t iCmdDelayS, iCmdDelayL; - int iConvTableLen; - uint8_t *piConvTable; - - uint8_t *data; - int iLength; - int iPos; - int iDelay; - - - public: - static CPlayer *factory(Copl *newopl); - - Cdro2Player(Copl *newopl); - ~Cdro2Player(); - - bool load(VFSFile &fd, const CFileProvider &fp); - bool update(); - void rewind(int subsong); - float getrefresh(); - - std::string gettype() - { - return std::string("DOSBox Raw OPL v2.0"); - } - - protected: - //unsigned char *data; - //unsigned long pos,length; - //unsigned long msdone,mstotal; - //unsigned short delay; - //unsigned char index, opl3_mode; + protected: + uint8_t iCmdDelayS, iCmdDelayL; + int iConvTableLen; + uint8_t *piConvTable; + + uint8_t *data; + int iLength; + int iPos; + int iDelay; + + + public: + static CPlayer *factory(Copl *newopl); + + Cdro2Player(Copl *newopl); + ~Cdro2Player(); + + bool load(const std::string &filename, const CFileProvider &fp); + bool update(); + void rewind(int subsong); + float getrefresh(); + + std::string gettype() + { + return std::string("DOSBox Raw OPL v2.0"); + } + + protected: + //unsigned char *data; + //unsigned long pos,length; + //unsigned long msdone,mstotal; + //unsigned short delay; + //unsigned char index, opl3_mode; }; diff --git a/src/adplug/core/dtm.cc b/src/adplug/core/dtm.cc index 9b8bcc5..4a4a130 100644 --- a/src/adplug/core/dtm.cc +++ b/src/adplug/core/dtm.cc @@ -22,289 +22,268 @@ NOTE: Panning (Ex) effect is ignored. */ -#include <string.h> - +#include <cstring> #include "dtm.h" /* -------- Public Methods -------------------------------- */ -CPlayer * -CdtmLoader::factory (Copl * newopl) +CPlayer *CdtmLoader::factory(Copl *newopl) { - return new CdtmLoader (newopl); + return new CdtmLoader(newopl); } -bool -CdtmLoader::load (VFSFile & fd, const CFileProvider & fp) +bool CdtmLoader::load(const std::string &filename, const CFileProvider &fp) { - binistream *f = fp.open (fd); - if (!f) - return false; - const unsigned char conv_inst[11] = { 2, 1, 10, 9, 4, 3, 6, 5, 0, 8, 7 }; - const unsigned short conv_note[12] = - { 0x16B, 0x181, 0x198, 0x1B0, 0x1CA, 0x1E5, 0x202, 0x220, 0x241, 0x263, -0x287, 0x2AE }; - - int i, j, k, t = 0; + binistream *f = fp.open(filename); if(!f) return false; + const unsigned char conv_inst[11] = { 2,1,10,9,4,3,6,5,0,8,7 }; + const unsigned short conv_note[12] = { 0x16B, 0x181, 0x198, 0x1B0, 0x1CA, 0x1E5, 0x202, 0x220, 0x241, 0x263, 0x287, 0x2AE }; + int i,j,k,t=0; // read header - f->readString (header.id, 12); - header.version = f->readInt (1); - f->readString (header.title, 20); - f->readString (header.author, 20); - header.numpat = f->readInt (1); - header.numinst = f->readInt (1); + f->readString(header.id, 12); + header.version = f->readInt(1); + f->readString(header.title, 20); f->readString(header.author, 20); + header.numpat = f->readInt(1); header.numinst = f->readInt(1); // signature exists ? good version ? - if (memcmp (header.id, "DeFy DTM ", 9) || header.version != 0x10) - { - fp.close (f); - return false; - } + if(memcmp(header.id,"DeFy DTM ",9) || header.version != 0x10) + { fp.close (f); return false; } header.numinst++; // load description - memset (desc, 0, 80 * 16); + memset(desc,0,80*16); char bufstr[80]; - for (i = 0; i < 16; i++) - { - // get line length - unsigned char bufstr_length = f->readInt (1); - - if (bufstr_length > 80) + for (i=0;i<16;i++) { - fp.close (f); - return false; - } + // get line length + unsigned char bufstr_length = f->readInt(1); - // read line - if (bufstr_length) - { - f->readString (bufstr, bufstr_length); + if(bufstr_length > 80) { + fp.close(f); + return false; + } + + // read line + if (bufstr_length) + { + f->readString(bufstr,bufstr_length); - for (j = 0; j < bufstr_length; j++) - if (!bufstr[j]) - bufstr[j] = 0x20; + for (j=0;j<bufstr_length;j++) + if (!bufstr[j]) + bufstr[j] = 0x20; - bufstr[bufstr_length] = 0; + bufstr[bufstr_length] = 0; - strcat (desc, bufstr); - } + strcat(desc,bufstr); + } - strcat (desc, "\n"); - } + strcat(desc,"\n"); + } // init CmodPlayer - realloc_instruments (header.numinst); - realloc_order (100); - realloc_patterns (header.numpat, 64, 9); - init_notetable (conv_note); - init_trackord (); + realloc_instruments(header.numinst); + realloc_order(100); + realloc_patterns(header.numpat,64,9); + init_notetable(conv_note); + init_trackord(); // load instruments - for (i = 0; i < header.numinst; i++) - { - unsigned char name_length = f->readInt (1); + for (i=0;i<header.numinst;i++) + { + unsigned char name_length = f->readInt(1); - if (name_length) - f->readString (instruments[i].name, name_length); + if (name_length) + f->readString(instruments[i].name, name_length); - instruments[i].name[name_length] = 0; + instruments[i].name[name_length] = 0; - for (j = 0; j < 12; j++) - instruments[i].data[j] = f->readInt (1); + for(j = 0; j < 12; j++) + instruments[i].data[j] = f->readInt(1); - for (j = 0; j < 11; j++) - inst[i].data[conv_inst[j]] = instruments[i].data[j]; - } + for (j=0;j<11;j++) + inst[i].data[conv_inst[j]] = instruments[i].data[j]; + } // load order - for (i = 0; i < 100; i++) - order[i] = f->readInt (1); + for(i = 0; i < 100; i++) order[i] = f->readInt(1); nop = header.numpat; - unsigned char *pattern = new unsigned char[0x480]; + unsigned char *pattern = new unsigned char [0x480]; // load tracks - for (i = 0; i < nop; i++) - { - unsigned short packed_length; - - packed_length = f->readInt (2); + for (i=0;i<nop;i++) + { + unsigned short packed_length; - unsigned char *packed_pattern = new unsigned char[packed_length]; + packed_length = f->readInt(2); - for (j = 0; j < packed_length; j++) - packed_pattern[j] = f->readInt (1); + unsigned char *packed_pattern = new unsigned char [packed_length]; - long unpacked_length = - unpack_pattern (packed_pattern, packed_length, pattern, 0x480); + for(j = 0; j < packed_length; j++) + packed_pattern[j] = f->readInt(1); - delete[]packed_pattern; + long unpacked_length = unpack_pattern(packed_pattern,packed_length,pattern,0x480); - if (!unpacked_length) - { - delete[] pattern; - fp.close (f); - return false; - } + delete [] packed_pattern; - // convert pattern - for (j = 0; j < 9; j++) - { - for (k = 0; k < 64; k++) - { - dtm_event *event = (dtm_event *) & pattern[(k * 9 + j) * 2]; - - // instrument - if (event->byte0 == 0x80) + if (!unpacked_length) { - if (event->byte1 <= 0x80) - tracks[t][k].inst = event->byte1 + 1; + delete [] pattern; + fp.close(f); + return false; } - // note + effect - else + // convert pattern + for (j=0;j<9;j++) { - tracks[t][k].note = event->byte0; - - if ((event->byte0 != 0) && (event->byte0 != 127)) - tracks[t][k].note++; - - // convert effects - switch (event->byte1 >> 4) - { - case 0x0: // pattern break - if ((event->byte1 & 15) == 1) - tracks[t][k].command = 13; - break; - - case 0x1: // freq. slide up - tracks[t][k].command = 28; - tracks[t][k].param1 = event->byte1 & 15; - break; - - case 0x2: // freq. slide down - tracks[t][k].command = 28; - tracks[t][k].param2 = event->byte1 & 15; - break; - - case 0xA: // set carrier volume - case 0xC: // set instrument volume - tracks[t][k].command = 22; - tracks[t][k].param1 = (0x3F - (event->byte1 & 15)) >> 4; - tracks[t][k].param2 = (0x3F - (event->byte1 & 15)) & 15; - break; - - case 0xB: // set modulator volume - tracks[t][k].command = 21; - tracks[t][k].param1 = (0x3F - (event->byte1 & 15)) >> 4; - tracks[t][k].param2 = (0x3F - (event->byte1 & 15)) & 15; - break; - - case 0xE: // set panning - break; - - case 0xF: // set speed - tracks[t][k].command = 13; - tracks[t][k].param2 = event->byte1 & 15; - break; - } + for (k=0;k<64;k++) + { + dtm_event *event = (dtm_event *)&pattern[(k*9+j)*2]; + + // instrument + if (event->byte0 == 0x80) + { + if (event->byte1 <= 0x80) + tracks[t][k].inst = event->byte1 + 1; + } + + // note + effect + else + { + tracks[t][k].note = event->byte0; + + if ((event->byte0 != 0) && (event->byte0 != 127)) + tracks[t][k].note++; + + // convert effects + switch (event->byte1 >> 4) + { + case 0x0: // pattern break + if ((event->byte1 & 15) == 1) + tracks[t][k].command = 13; + break; + + case 0x1: // freq. slide up + tracks[t][k].command = 28; + tracks[t][k].param1 = event->byte1 & 15; + break; + + case 0x2: // freq. slide down + tracks[t][k].command = 28; + tracks[t][k].param2 = event->byte1 & 15; + break; + + case 0xA: // set carrier volume + case 0xC: // set instrument volume + tracks[t][k].command = 22; + tracks[t][k].param1 = (0x3F - (event->byte1 & 15)) >> 4; + tracks[t][k].param2 = (0x3F - (event->byte1 & 15)) & 15; + break; + + case 0xB: // set modulator volume + tracks[t][k].command = 21; + tracks[t][k].param1 = (0x3F - (event->byte1 & 15)) >> 4; + tracks[t][k].param2 = (0x3F - (event->byte1 & 15)) & 15; + break; + + case 0xE: // set panning + break; + + case 0xF: // set speed + tracks[t][k].command = 13; + tracks[t][k].param2 = event->byte1 & 15; + break; + } + } + } + + t++; } - } - - t++; } - } - delete[]pattern; - fp.close (f); + delete [] pattern; + fp.close(f); // order length - for (i = 0; i < 100; i++) - { - if (order[i] >= 0x80) + for (i=0;i<100;i++) { - length = i; + if (order[i] >= 0x80) + { + length = i; - if (order[i] == 0xFF) - restartpos = 0; - else - restartpos = order[i] - 0x80; + if (order[i] == 0xFF) + restartpos = 0; + else + restartpos = order[i] - 0x80; - break; + break; + } } - } // initial speed initspeed = 2; - rewind (0); + rewind(0); return true; } -void -CdtmLoader::rewind (int subsong) +void CdtmLoader::rewind(int subsong) { - CmodPlayer::rewind (subsong); + CmodPlayer::rewind(subsong); // default instruments - for (int i = 0; i < 9; i++) - { - channel[i].inst = i; + for (int i=0;i<9;i++) + { + channel[i].inst = i; - channel[i].vol1 = 63 - (inst[i].data[10] & 63); - channel[i].vol2 = 63 - (inst[i].data[9] & 63); - } + channel[i].vol1 = 63 - (inst[i].data[10] & 63); + channel[i].vol2 = 63 - (inst[i].data[9] & 63); + } } -float -CdtmLoader::getrefresh () +float CdtmLoader::getrefresh() { return 18.2f; } -std::string CdtmLoader::gettype () +std::string CdtmLoader::gettype() { - return std::string ("DeFy Adlib Tracker"); + return std::string("DeFy Adlib Tracker"); } -std::string CdtmLoader::gettitle () +std::string CdtmLoader::gettitle() { - return std::string (header.title); + return std::string(header.title); } -std::string CdtmLoader::getauthor () +std::string CdtmLoader::getauthor() { - return std::string (header.author); + return std::string(header.author); } -std::string CdtmLoader::getdesc () +std::string CdtmLoader::getdesc() { - return std::string (desc); + return std::string(desc); } -std::string CdtmLoader::getinstrument (unsigned int n) +std::string CdtmLoader::getinstrument(unsigned int n) { - return std::string (instruments[n].name); + return std::string(instruments[n].name); } -unsigned int -CdtmLoader::getinstruments () +unsigned int CdtmLoader::getinstruments() { return header.numinst; } /* -------- Private Methods ------------------------------- */ -long -CdtmLoader::unpack_pattern (unsigned char *ibuf, long ilen, - unsigned char *obuf, long olen) +long CdtmLoader::unpack_pattern(unsigned char *ibuf, long ilen, unsigned char *obuf, long olen) { unsigned char *input = ibuf; unsigned char *output = obuf; @@ -316,23 +295,23 @@ CdtmLoader::unpack_pattern (unsigned char *ibuf, long ilen, // RLE while (input_length < ilen) - { - repeat_byte = input[input_length++]; - - if ((repeat_byte & 0xF0) == 0xD0) { - repeat_counter = repeat_byte & 15; repeat_byte = input[input_length++]; - } - else - repeat_counter = 1; - for (int i = 0; i < repeat_counter; i++) - { - if (output_length < olen) - output[output_length++] = repeat_byte; + if ((repeat_byte & 0xF0) == 0xD0) + { + repeat_counter = repeat_byte & 15; + repeat_byte = input[input_length++]; + } + else + repeat_counter = 1; + + for (int i=0;i<repeat_counter;i++) + { + if (output_length < olen) + output[output_length++] = repeat_byte; + } } - } return output_length; } diff --git a/src/adplug/core/dtm.h b/src/adplug/core/dtm.h index de33dfe..fdcc37e 100644 --- a/src/adplug/core/dtm.h +++ b/src/adplug/core/dtm.h @@ -23,47 +23,47 @@ class CdtmLoader: public CmodPlayer { - public: - static CPlayer *factory(Copl *newopl); + public: + static CPlayer *factory(Copl *newopl); - CdtmLoader(Copl *newopl) : CmodPlayer(newopl) { }; + CdtmLoader(Copl *newopl) : CmodPlayer(newopl) { }; - bool load(VFSFile &fd, const CFileProvider &fp); - void rewind(int subsong); - float getrefresh(); + bool load(const std::string &filename, const CFileProvider &fp); + void rewind(int subsong); + float getrefresh(); - std::string gettype(); - std::string gettitle(); - std::string getauthor(); - std::string getdesc(); - std::string getinstrument(unsigned int n); - unsigned int getinstruments(); + std::string gettype(); + std::string gettitle(); + std::string getauthor(); + std::string getdesc(); + std::string getinstrument(unsigned int n); + unsigned int getinstruments(); - private: + private: - struct dtm_header - { - char id[12]; - unsigned char version; - char title[20]; - char author[20]; - unsigned char numpat; - unsigned char numinst; - } header; + struct dtm_header + { + char id[12]; + unsigned char version; + char title[20]; + char author[20]; + unsigned char numpat; + unsigned char numinst; + } header; - char desc[80*16]; + char desc[80*16]; - struct dtm_instrument - { - char name[13]; - unsigned char data[12]; - } instruments[128]; + struct dtm_instrument + { + char name[13]; + unsigned char data[12]; + } instruments[128]; - struct dtm_event - { - unsigned char byte0; - unsigned char byte1; - }; + struct dtm_event + { + unsigned char byte0; + unsigned char byte1; + }; - long unpack_pattern(unsigned char *ibuf, long ilen, unsigned char *obuf, long olen); + long unpack_pattern(unsigned char *ibuf, long ilen, unsigned char *obuf, long olen); }; diff --git a/src/adplug/core/emuopl.cc b/src/adplug/core/emuopl.cc index c3284c7..6e20845 100644 --- a/src/adplug/core/emuopl.cc +++ b/src/adplug/core/emuopl.cc @@ -1,17 +1,17 @@ /* * AdPlug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2005 Simon Peter <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -21,47 +21,39 @@ #include "emuopl.h" -CEmuopl::CEmuopl (int rate, bool bit16, bool usestereo):use16bit (bit16), stereo (usestereo), -mixbufSamples (0) +CEmuopl::CEmuopl(int rate, bool bit16, bool usestereo) + : use16bit(bit16), stereo(usestereo), mixbufSamples(0) { - opl[0] = OPLCreate (OPL_TYPE_YM3812, 3579545, rate); - opl[1] = OPLCreate (OPL_TYPE_YM3812, 3579545, rate); + opl[0] = OPLCreate(OPL_TYPE_YM3812, 3579545, rate); + opl[1] = OPLCreate(OPL_TYPE_YM3812, 3579545, rate); currType = TYPE_DUAL_OPL2; - init (); + init(); } -CEmuopl::~CEmuopl () +CEmuopl::~CEmuopl() { - OPLDestroy (opl[0]); - OPLDestroy (opl[1]); + OPLDestroy(opl[0]); OPLDestroy(opl[1]); - if (mixbufSamples) - { - delete[]mixbuf0; - delete[]mixbuf1; + if(mixbufSamples) { + delete [] mixbuf0; + delete [] mixbuf1; } } -void -CEmuopl::update (short *buf, int samples) +void CEmuopl::update(short *buf, int samples) { int i; //ensure that our mix buffers are adequately sized - if (mixbufSamples < samples) - { - if (mixbufSamples) - { - delete[]mixbuf0; - delete[]mixbuf1; - } + if(mixbufSamples < samples) { + if(mixbufSamples) { delete[] mixbuf0; delete[] mixbuf1; } mixbufSamples = samples; //*2 = make room for stereo, if we need it - mixbuf0 = new short[samples * 2]; - mixbuf1 = new short[samples * 2]; + mixbuf0 = new short[samples*2]; + mixbuf1 = new short[samples*2]; } //data should be rendered to outbuf @@ -73,94 +65,83 @@ CEmuopl::update (short *buf, int samples) //and so it must point to a mixbuf instead-- //it will be reduced to 8bit and put in "buf" later short *outbuf; - short *tempbuf = mixbuf0; - short *tempbuf2 = mixbuf1; - if (use16bit) - outbuf = buf; - else - outbuf = mixbuf1; + short *tempbuf=mixbuf0; + short *tempbuf2=mixbuf1; + if(use16bit) outbuf = buf; + else outbuf = mixbuf1; //...there is a potentially confusing situation where mixbuf1 can be aliased. //beware. it is a little loony. //all of the following rendering code produces 16bit output - switch (currType) - { + switch(currType) { case TYPE_OPL2: //for opl2 mode: //render chip0 to the output buffer - YM3812UpdateOne (opl[0], outbuf, samples); + YM3812UpdateOne(opl[0],outbuf,samples); //if we are supposed to output stereo, //then we need to dup the mono channel - if (stereo) - for (i = samples - 1; i >= 0; i--) - { - outbuf[i * 2] = outbuf[i]; - outbuf[i * 2 + 1] = outbuf[i]; + if(stereo) + for(i=samples-1;i>=0;i--) { + outbuf[i*2] = outbuf[i]; + outbuf[i*2+1] = outbuf[i]; } break; - case TYPE_OPL3: // unsupported + case TYPE_OPL3: // unsupported break; case TYPE_DUAL_OPL2: //for dual opl2 mode: //render each chip to a different tempbuffer - YM3812UpdateOne (opl[0], tempbuf2, samples); - YM3812UpdateOne (opl[1], tempbuf, samples); + YM3812UpdateOne(opl[0],tempbuf2,samples); + YM3812UpdateOne(opl[1],tempbuf,samples); //output stereo: //then we need to interleave the two buffers - if (stereo) - { + if(stereo){ //first, spread tempbuf's samples across left channel //left channel - for (i = 0; i < samples; i++) - outbuf[i * 2] = tempbuf2[i]; + for(i=0;i<samples;i++) + outbuf[i*2] = tempbuf2[i]; //next, insert the samples from tempbuf2 into right channel - for (i = 0; i < samples; i++) - outbuf[i * 2 + 1] = tempbuf[i]; - } - else + for(i=0;i<samples;i++) + outbuf[i*2+1] = tempbuf[i]; + } else //output mono: //then we need to mix the two buffers into buf - for (i = 0; i < samples; i++) - outbuf[i] = (tempbuf[i] >> 1) + (tempbuf2[i] >> 1); + for(i=0;i<samples;i++) + outbuf[i] = (tempbuf[i]>>1) + (tempbuf2[i]>>1); break; } //now reduce to 8bit if we need to - if (!use16bit) - for (i = 0; i < (stereo ? samples * 2 : samples); i++) - ((char *) buf)[i] = (outbuf[i] >> 8) ^ 0x80; + if(!use16bit) + for(i=0;i<(stereo ? samples*2 : samples);i++) + ((char *)buf)[i] = (outbuf[i] >> 8) ^ 0x80; } -void -CEmuopl::write (int reg, int val) +void CEmuopl::write(int reg, int val) { - switch (currType) - { + switch(currType){ case TYPE_OPL2: case TYPE_DUAL_OPL2: - OPLWrite (opl[currChip], 0, reg); - OPLWrite (opl[currChip], 1, val); + OPLWrite(opl[currChip], 0, reg); + OPLWrite(opl[currChip], 1, val); break; - case TYPE_OPL3: // unsupported + case TYPE_OPL3: // unsupported break; } } -void -CEmuopl::init () +void CEmuopl::init() { - OPLResetChip (opl[0]); - OPLResetChip (opl[1]); + OPLResetChip(opl[0]); OPLResetChip(opl[1]); currChip = 0; } -void -CEmuopl::settype (ChipType type) +void CEmuopl::settype(ChipType type) { currType = type; } diff --git a/src/adplug/core/emuopl.h b/src/adplug/core/emuopl.h index 51ea06e..e65d49e 100644 --- a/src/adplug/core/emuopl.h +++ b/src/adplug/core/emuopl.h @@ -28,20 +28,20 @@ class CEmuopl: public Copl { public: - CEmuopl(int rate, bool bit16, bool usestereo); // rate = sample rate + CEmuopl(int rate, bool bit16, bool usestereo); // rate = sample rate virtual ~CEmuopl(); - void update(short *buf, int samples); // fill buffer + void update(short *buf, int samples); // fill buffer void write(int reg, int val); void init(); void settype(ChipType type); private: - bool use16bit, stereo; - FM_OPL *opl[2]; // OPL2 emulator data - short *mixbuf0, *mixbuf1; - int mixbufSamples; + bool use16bit, stereo; + FM_OPL *opl[2]; // OPL2 emulator data + short *mixbuf0, *mixbuf1; + int mixbufSamples; }; #endif diff --git a/src/adplug/core/flash.cc b/src/adplug/core/flash.cc index 30df8b0..cc63729 100644 --- a/src/adplug/core/flash.cc +++ b/src/adplug/core/flash.cc @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -31,8 +31,8 @@ #include "flash.h" #include "debug.h" -const unsigned char - CxadflashPlayer::flash_adlib_registers[99] = { +const unsigned char CxadflashPlayer::flash_adlib_registers[99] = +{ 0x23, 0x20, 0x43, 0x40, 0x63, 0x60, 0x83, 0x80, 0xC0, 0xE3, 0xE0, 0x24, 0x21, 0x44, 0x41, 0x64, 0x61, 0x84, 0x81, 0xC1, 0xE4, 0xE1, 0x25, 0x22, 0x45, 0x42, 0x65, 0x62, 0x85, 0x82, 0xC2, 0xE5, 0xE2, @@ -44,73 +44,49 @@ const unsigned char 0x35, 0x32, 0x55, 0x52, 0x75, 0x72, 0x95, 0x92, 0xC8, 0xF5, 0xF2 }; -const unsigned short - CxadflashPlayer::flash_notes_encoded[268] = { +const unsigned short CxadflashPlayer::flash_notes_encoded[268] = +{ 0x000, - 0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x700, 0x800, 0x900, 0xA00, 0xB00, - 0xC00, - 0x101, 0x201, 0x301, 0x401, 0x501, 0x601, 0x701, 0x801, 0x901, 0xA01, 0xB01, - 0xC01, - 0x102, 0x202, 0x302, 0x402, 0x502, 0x602, 0x702, 0x802, 0x902, 0xA02, 0xB02, - 0xC02, - 0x103, 0x203, 0x303, 0x403, 0x503, 0x603, 0x703, 0x803, 0x903, 0xA03, 0xB03, - 0xC03, - 0x104, 0x204, 0x304, 0x404, 0x504, 0x604, 0x704, 0x804, 0x904, 0xA04, 0xB04, - 0xC04, - 0x105, 0x205, 0x305, 0x405, 0x505, 0x605, 0x705, 0x805, 0x905, 0xA05, 0xB05, - 0xC05, - 0x106, 0x206, 0x306, 0x406, 0x506, 0x606, 0x706, 0x806, 0x906, 0xA06, 0xB06, - 0xC06, - 0x107, 0x207, 0x307, 0x407, 0x507, 0x607, 0x707, 0x807, 0x907, 0xA07, 0xB07, - 0xC07, - 0x108, 0x208, 0x308, 0x408, 0x508, 0x608, 0x708, 0x808, 0x908, 0xA08, 0xB08, - 0xC08, - 0x109, 0x209, 0x309, 0x409, 0x509, 0x609, 0x709, 0x809, 0x909, 0xA09, 0xB09, - 0xC09, - 0x10A, 0x20A, 0x30A, 0x40A, 0x50A, 0x60A, 0x70A, 0x80A, 0x90A, 0xA0A, 0xB0A, - 0xC0A, - 0x10B, 0x20B, 0x30B, 0x40B, 0x50B, 0x60B, 0x70B, 0x80B, 0x90B, 0xA0B, 0xB0B, - 0xC0B, - 0x10C, 0x20C, 0x30C, 0x40C, 0x50C, 0x60C, 0x70C, 0x80C, 0x90C, 0xA0C, 0xB0C, - 0xC0C, - 0x10D, 0x20D, 0x30D, 0x40D, 0x50D, 0x60D, 0x70D, 0x80D, 0x90D, 0xA0D, 0xB0D, - 0xC0D, - 0x10E, 0x20E, 0x30E, 0x40E, 0x50E, 0x60E, 0x70E, 0x80E, 0x90E, 0xA0E, 0xB0E, - 0xC0E, - 0x10F, 0x20F, 0x30F, 0x40F, 0x50F, 0x60F, 0x70F, 0x80F, 0x90F, 0xA0F, 0xB0F, - 0xC0F, - 0x110, 0x210, 0x310, 0x410, 0x510, 0x610, 0x710, 0x810, 0x910, 0xA10, 0xB10, - 0xC10, - 0x111, 0x211, 0x311, 0x411, 0x511, 0x611, 0x711, 0x811, 0x911, 0xA11, 0xB11, - 0xC11, - 0x112, 0x212, 0x312, 0x412, 0x512, 0x612, 0x712, 0x812, 0x912, 0xA12, 0xB12, - 0xC12, - 0x113, 0x213, 0x313, 0x413, 0x513, 0x613, 0x713, 0x813, 0x913, 0xA13, 0xB13, - 0xC13, - 0x114, 0x214, 0x314, 0x414, 0x514, 0x614, 0x714, 0x814, 0x914, 0xA14, 0xB14, - 0xC14, + 0x100, 0x200, 0x300, 0x400, 0x500, 0x600, 0x700, 0x800, 0x900, 0xA00, 0xB00, 0xC00, + 0x101, 0x201, 0x301, 0x401, 0x501, 0x601, 0x701, 0x801, 0x901, 0xA01, 0xB01, 0xC01, + 0x102, 0x202, 0x302, 0x402, 0x502, 0x602, 0x702, 0x802, 0x902, 0xA02, 0xB02, 0xC02, + 0x103, 0x203, 0x303, 0x403, 0x503, 0x603, 0x703, 0x803, 0x903, 0xA03, 0xB03, 0xC03, + 0x104, 0x204, 0x304, 0x404, 0x504, 0x604, 0x704, 0x804, 0x904, 0xA04, 0xB04, 0xC04, + 0x105, 0x205, 0x305, 0x405, 0x505, 0x605, 0x705, 0x805, 0x905, 0xA05, 0xB05, 0xC05, + 0x106, 0x206, 0x306, 0x406, 0x506, 0x606, 0x706, 0x806, 0x906, 0xA06, 0xB06, 0xC06, + 0x107, 0x207, 0x307, 0x407, 0x507, 0x607, 0x707, 0x807, 0x907, 0xA07, 0xB07, 0xC07, + 0x108, 0x208, 0x308, 0x408, 0x508, 0x608, 0x708, 0x808, 0x908, 0xA08, 0xB08, 0xC08, + 0x109, 0x209, 0x309, 0x409, 0x509, 0x609, 0x709, 0x809, 0x909, 0xA09, 0xB09, 0xC09, + 0x10A, 0x20A, 0x30A, 0x40A, 0x50A, 0x60A, 0x70A, 0x80A, 0x90A, 0xA0A, 0xB0A, 0xC0A, + 0x10B, 0x20B, 0x30B, 0x40B, 0x50B, 0x60B, 0x70B, 0x80B, 0x90B, 0xA0B, 0xB0B, 0xC0B, + 0x10C, 0x20C, 0x30C, 0x40C, 0x50C, 0x60C, 0x70C, 0x80C, 0x90C, 0xA0C, 0xB0C, 0xC0C, + 0x10D, 0x20D, 0x30D, 0x40D, 0x50D, 0x60D, 0x70D, 0x80D, 0x90D, 0xA0D, 0xB0D, 0xC0D, + 0x10E, 0x20E, 0x30E, 0x40E, 0x50E, 0x60E, 0x70E, 0x80E, 0x90E, 0xA0E, 0xB0E, 0xC0E, + 0x10F, 0x20F, 0x30F, 0x40F, 0x50F, 0x60F, 0x70F, 0x80F, 0x90F, 0xA0F, 0xB0F, 0xC0F, + 0x110, 0x210, 0x310, 0x410, 0x510, 0x610, 0x710, 0x810, 0x910, 0xA10, 0xB10, 0xC10, + 0x111, 0x211, 0x311, 0x411, 0x511, 0x611, 0x711, 0x811, 0x911, 0xA11, 0xB11, 0xC11, + 0x112, 0x212, 0x312, 0x412, 0x512, 0x612, 0x712, 0x812, 0x912, 0xA12, 0xB12, 0xC12, + 0x113, 0x213, 0x313, 0x413, 0x513, 0x613, 0x713, 0x813, 0x913, 0xA13, 0xB13, 0xC13, + 0x114, 0x214, 0x314, 0x414, 0x514, 0x614, 0x714, 0x814, 0x914, 0xA14, 0xB14, 0xC14, 0x115, 0x215, 0x315 }; -const unsigned short - CxadflashPlayer::flash_notes[12] = { - 0x157, 0x16B, 0x181, 0x198, 0x1B0, 0x1CA, 0x1E5, 0x202, 0x220, 0x241, 0x263, - 0x287 +const unsigned short CxadflashPlayer::flash_notes[12] = +{ + 0x157, 0x16B, 0x181, 0x198, 0x1B0, 0x1CA, 0x1E5, 0x202, 0x220, 0x241, 0x263, 0x287 }; -const unsigned char - CxadflashPlayer::flash_default_instrument[8] = { +const unsigned char CxadflashPlayer::flash_default_instrument[8] = +{ 0x00, 0x00, 0x3F, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF }; -CPlayer * -CxadflashPlayer::factory (Copl * newopl) +CPlayer *CxadflashPlayer::factory(Copl *newopl) { - return new CxadflashPlayer (newopl); + return new CxadflashPlayer(newopl); } -void -CxadflashPlayer::xadplayer_rewind (int subsong) +void CxadflashPlayer::xadplayer_rewind(int subsong) { int i; @@ -119,77 +95,74 @@ CxadflashPlayer::xadplayer_rewind (int subsong) flash.order_pos = 0; flash.pattern_pos = 0; - opl_write (0x08, 0x00); - opl_write (0xBD, 0x00); + opl_write(0x08, 0x00); + opl_write(0xBD, 0x00); // assign default instrument - for (i = 0; i < 9; i++) + for(i=0; i<9; i++) { - opl_write (0xA0 + i, 0x00); - opl_write (0xB0 + i, 0x00); + opl_write(0xA0+i, 0x00); + opl_write(0xB0+i, 0x00); } // assign instruments - for (i = 0; i < 9; i++) - for (int j = 0; j < 11; j++) - opl_write (flash_adlib_registers[i * 11 + j], tune[i * 12 + j]); + for(i=0; i<9; i++) + for(int j=0; j<11; j++) + opl_write(flash_adlib_registers[i*11+j], tune[i*12+j]); } -void -CxadflashPlayer::xadplayer_update () +void CxadflashPlayer::xadplayer_update() { - unsigned short event_pos = (tune[0x600 + flash.order_pos] * 1152) + - (flash.pattern_pos * 18) + 0x633; + unsigned short event_pos = (tune[0x600+flash.order_pos]*1152) + \ + (flash.pattern_pos*18) + \ + 0x633; - for (int i = 0; i < 9; i++) + for (int i=0; i<9; i++) { - unsigned short flash_channel_freq = - (adlib[0xB0 + i] << 8) + adlib[0xA0 + i]; + unsigned short flash_channel_freq = (adlib[0xB0+i] << 8) + adlib[0xA0+i]; unsigned char event_b0 = tune[event_pos++]; unsigned char event_b1 = tune[event_pos++]; #ifdef DEBUG - AdPlug_LogWrite ("channel %02X, event %02X %02X:\n", i + 1, event_b0, - event_b1); + AdPlug_LogWrite("channel %02X, event %02X %02X:\n",i+1,event_b0,event_b1); #endif - if (event_b0 == 0x80) // 0.0x80: Set Instrument + if (event_b0 == 0x80) // 0.0x80: Set Instrument { - for (int j = 0; j < 11; j++) - opl_write (flash_adlib_registers[i * 11 + j], - tune[event_b1 * 12 + j]); + for(int j=0; j<11; j++) + opl_write(flash_adlib_registers[i*11+j], tune[event_b1*12+j]); } else { if (event_b1 == 0x01) - flash.pattern_pos = 0x3F; // 1.0x01: Pattern Break + flash.pattern_pos = 0x3F; // 1.0x01: Pattern Break unsigned char fx = (event_b1 >> 4); unsigned char fx_p = (event_b1 & 0x0F); - switch (fx) + switch(fx) { - case 0x0A: // 1.0xAy: Set Carrier volume - opl_write (flash_adlib_registers[11 * i + 2], fx_p << 2); - break; - case 0x0B: // 1.0xBy: Set Modulator volume - opl_write (flash_adlib_registers[11 * i + 3], fx_p << 2); - break; - case 0x0C: // 1.0xCy: Set both operators volume - opl_write (flash_adlib_registers[11 * i + 2], fx_p << 2); - opl_write (flash_adlib_registers[11 * i + 3], fx_p << 2); - break; + case 0x0A: // 1.0xAy: Set Carrier volume + opl_write(flash_adlib_registers[11*i+2], fx_p << 2); + break; + case 0x0B: // 1.0xBy: Set Modulator volume + opl_write(flash_adlib_registers[11*i+3], fx_p << 2); + break; + case 0x0C: // 1.0xCy: Set both operators volume + opl_write(flash_adlib_registers[11*i+2], fx_p << 2); + opl_write(flash_adlib_registers[11*i+3], fx_p << 2); + break; // case 0x0E: // 1.0xEy: ? (increase some value) - case 0x0F: // 1.0xFy: Set Speed - plr.speed = (fx_p + 1); - break; + case 0x0F: // 1.0xFy: Set Speed + plr.speed = (fx_p + 1); + break; } if (event_b0) { // mute channel - opl_write (0xA0 + i, adlib[0xA0 + i]); - opl_write (0xB0 + i, adlib[0xB0 + i] & 0xDF); + opl_write(0xA0+i, adlib[0xA0+i]); + opl_write(0xB0+i, adlib[0xB0+i] & 0xDF); // is note ? if (event_b0 != 0x7F) @@ -199,24 +172,24 @@ CxadflashPlayer::xadplayer_update () flash_channel_freq = freq | ((note_encoded & 0xFF) << 10) | 0x2000; - opl_write (0xA0 + i, flash_channel_freq & 0xFF); - opl_write (0xB0 + i, flash_channel_freq >> 8); + opl_write(0xA0+i, flash_channel_freq & 0xFF); + opl_write(0xB0+i, flash_channel_freq >> 8); } } - if (fx == 0x01) // 1.0x1y: Fine Frequency Slide Up + if (fx == 0x01) // 1.0x1y: Fine Frequency Slide Up { flash_channel_freq += (fx_p << 1); - opl_write (0xA0 + i, flash_channel_freq & 0xFF); - opl_write (0xB0 + i, flash_channel_freq >> 8); + opl_write(0xA0+i, flash_channel_freq & 0xFF); + opl_write(0xB0+i, flash_channel_freq >> 8); } - else if (fx == 0x02) // 1.0x2y: Fine Frequency Slide Down + else if (fx == 0x02) // 1.0x2y: Fine Frequency Slide Down { flash_channel_freq -= (fx_p << 1); - opl_write (0xA0 + i, flash_channel_freq & 0xFF); - opl_write (0xB0 + i, flash_channel_freq >> 8); + opl_write(0xA0+i, flash_channel_freq & 0xFF); + opl_write(0xB0+i, flash_channel_freq >> 8); } } } @@ -232,7 +205,7 @@ CxadflashPlayer::xadplayer_update () flash.order_pos++; // end of module ? - if (tune[0x600 + flash.order_pos] == 0xFF) + if (tune[0x600+flash.order_pos] == 0xFF) { flash.order_pos = 0; @@ -241,19 +214,17 @@ CxadflashPlayer::xadplayer_update () } } -float -CxadflashPlayer::xadplayer_getrefresh () +float CxadflashPlayer::xadplayer_getrefresh() { return 17.5f; } -std::string CxadflashPlayer::xadplayer_gettype () +std::string CxadflashPlayer::xadplayer_gettype() { - return std::string ("xad: flash player"); + return std::string("xad: flash player"); } -unsigned int -CxadflashPlayer::xadplayer_getinstruments () +unsigned int CxadflashPlayer::xadplayer_getinstruments() { return 32; } diff --git a/src/adplug/core/flash.h b/src/adplug/core/flash.h index f58512b..802bcb1 100644 --- a/src/adplug/core/flash.h +++ b/src/adplug/core/flash.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -36,12 +36,12 @@ protected: unsigned char pattern_pos; } flash; // - bool xadplayer_load() + bool xadplayer_load() { if(xad.fmt == FLASH) - return true; + return true; else - return false; + return false; } void xadplayer_rewind(int subsong); void xadplayer_update(); diff --git a/src/adplug/core/fmc.cc b/src/adplug/core/fmc.cc index c92bfba..ec37972 100644 --- a/src/adplug/core/fmc.cc +++ b/src/adplug/core/fmc.cc @@ -19,151 +19,136 @@ fmc.cpp - FMC Loader by Riven the Mage <riven@ok.ru> */ -#include <string.h> - +#include <cstring> #include "fmc.h" /* -------- Public Methods -------------------------------- */ -CPlayer * -CfmcLoader::factory (Copl * newopl) +CPlayer *CfmcLoader::factory(Copl *newopl) { - return new CfmcLoader (newopl); + return new CfmcLoader(newopl); } -bool -CfmcLoader::load (VFSFile & fd, const CFileProvider & fp) +bool CfmcLoader::load(const std::string &filename, const CFileProvider &fp) { - binistream *f = fp.open (fd); - if (!f) - return false; - const unsigned char conv_fx[16] = - { 0, 1, 2, 3, 4, 8, 255, 255, 255, 255, 26, 11, 12, 13, 14, 15 }; + binistream *f = fp.open(filename); if(!f) return false; + const unsigned char conv_fx[16] = {0,1,2,3,4,8,255,255,255,255,26,11,12,13,14,15}; - int i, j, k, t = 0; + int i,j,k,t=0; // read header - f->readString (header.id, 4); - f->readString (header.title, 21); - header.numchan = f->readInt (1); + f->readString(header.id, 4); + f->readString(header.title, 21); + header.numchan = f->readInt(1); // 'FMC!' - signed ? - if (strncmp (header.id, "FMC!", 4)) - { - fp.close (f); - return false; - } + if (strncmp(header.id,"FMC!",4)) { fp.close(f); return false; } // init CmodPlayer - realloc_instruments (32); - realloc_order (256); - realloc_patterns (64, 64, header.numchan); - init_trackord (); + realloc_instruments(32); + realloc_order(256); + realloc_patterns(64,64,header.numchan); + init_trackord(); // load order - for (i = 0; i < 256; i++) - order[i] = f->readInt (1); + for(i = 0; i < 256; i++) order[i] = f->readInt(1); - f->ignore (2); + f->ignore(2); // load instruments - for (i = 0; i < 32; i++) - { - instruments[i].synthesis = f->readInt (1); - instruments[i].feedback = f->readInt (1); - - instruments[i].mod_attack = f->readInt (1); - instruments[i].mod_decay = f->readInt (1); - instruments[i].mod_sustain = f->readInt (1); - instruments[i].mod_release = f->readInt (1); - instruments[i].mod_volume = f->readInt (1); - instruments[i].mod_ksl = f->readInt (1); - instruments[i].mod_freq_multi = f->readInt (1); - instruments[i].mod_waveform = f->readInt (1); - instruments[i].mod_sustain_sound = f->readInt (1); - instruments[i].mod_ksr = f->readInt (1); - instruments[i].mod_vibrato = f->readInt (1); - instruments[i].mod_tremolo = f->readInt (1); - - instruments[i].car_attack = f->readInt (1); - instruments[i].car_decay = f->readInt (1); - instruments[i].car_sustain = f->readInt (1); - instruments[i].car_release = f->readInt (1); - instruments[i].car_volume = f->readInt (1); - instruments[i].car_ksl = f->readInt (1); - instruments[i].car_freq_multi = f->readInt (1); - instruments[i].car_waveform = f->readInt (1); - instruments[i].car_sustain_sound = f->readInt (1); - instruments[i].car_ksr = f->readInt (1); - instruments[i].car_vibrato = f->readInt (1); - instruments[i].car_tremolo = f->readInt (1); - - instruments[i].pitch_shift = f->readInt (1); - - f->readString (instruments[i].name, 21); + for(i = 0; i < 32; i++) { + instruments[i].synthesis = f->readInt(1); + instruments[i].feedback = f->readInt(1); + + instruments[i].mod_attack = f->readInt(1); + instruments[i].mod_decay = f->readInt(1); + instruments[i].mod_sustain = f->readInt(1); + instruments[i].mod_release = f->readInt(1); + instruments[i].mod_volume = f->readInt(1); + instruments[i].mod_ksl = f->readInt(1); + instruments[i].mod_freq_multi = f->readInt(1); + instruments[i].mod_waveform = f->readInt(1); + instruments[i].mod_sustain_sound = f->readInt(1); + instruments[i].mod_ksr = f->readInt(1); + instruments[i].mod_vibrato = f->readInt(1); + instruments[i].mod_tremolo = f->readInt(1); + + instruments[i].car_attack = f->readInt(1); + instruments[i].car_decay = f->readInt(1); + instruments[i].car_sustain = f->readInt(1); + instruments[i].car_release = f->readInt(1); + instruments[i].car_volume = f->readInt(1); + instruments[i].car_ksl = f->readInt(1); + instruments[i].car_freq_multi = f->readInt(1); + instruments[i].car_waveform = f->readInt(1); + instruments[i].car_sustain_sound = f->readInt(1); + instruments[i].car_ksr = f->readInt(1); + instruments[i].car_vibrato = f->readInt(1); + instruments[i].car_tremolo = f->readInt(1); + + instruments[i].pitch_shift = f->readInt(1); + + f->readString(instruments[i].name, 21); } // load tracks - for (i = 0; i < 64; i++) - { - if (f->ateof ()) - break; - - for (j = 0; j < header.numchan; j++) + for (i=0;i<64;i++) { - for (k = 0; k < 64; k++) - { - fmc_event event; - - // read event - event.byte0 = f->readInt (1); - event.byte1 = f->readInt (1); - event.byte2 = f->readInt (1); - - // convert event - tracks[t][k].note = event.byte0 & 0x7F; - tracks[t][k].inst = - ((event.byte0 & 0x80) >> 3) + (event.byte1 >> 4) + 1; - tracks[t][k].command = conv_fx[event.byte1 & 0x0F]; - tracks[t][k].param1 = event.byte2 >> 4; - tracks[t][k].param2 = event.byte2 & 0x0F; - - // fix effects - if (tracks[t][k].command == 0x0E) // 0x0E (14): Retrig - tracks[t][k].param1 = 3; - if (tracks[t][k].command == 0x1A) // 0x1A (26): Volume Slide + if(f->ateof()) break; + + for (j=0;j<header.numchan;j++) { - if (tracks[t][k].param1 > tracks[t][k].param2) - { - tracks[t][k].param1 -= tracks[t][k].param2; - tracks[t][k].param2 = 0; - } - else - { - tracks[t][k].param2 -= tracks[t][k].param1; - tracks[t][k].param1 = 0; - } + for (k=0;k<64;k++) + { + fmc_event event; + + // read event + event.byte0 = f->readInt(1); + event.byte1 = f->readInt(1); + event.byte2 = f->readInt(1); + + // convert event + tracks[t][k].note = event.byte0 & 0x7F; + tracks[t][k].inst = ((event.byte0 & 0x80) >> 3) + (event.byte1 >> 4) + 1; + tracks[t][k].command = conv_fx[event.byte1 & 0x0F]; + tracks[t][k].param1 = event.byte2 >> 4; + tracks[t][k].param2 = event.byte2 & 0x0F; + + // fix effects + if (tracks[t][k].command == 0x0E) // 0x0E (14): Retrig + tracks[t][k].param1 = 3; + if (tracks[t][k].command == 0x1A) { // 0x1A (26): Volume Slide + if (tracks[t][k].param1 > tracks[t][k].param2) + { + tracks[t][k].param1 -= tracks[t][k].param2; + tracks[t][k].param2 = 0; + } + else + { + tracks[t][k].param2 -= tracks[t][k].param1; + tracks[t][k].param1 = 0; + } + } + } + + t++; } - } - - t++; } - } - fp.close (f); + fp.close(f); // convert instruments - for (i = 0; i < 31; i++) - buildinst (i); + for (i=0;i<31;i++) + buildinst(i); // order length - for (i = 0; i < 256; i++) - { - if (order[i] >= 0xFE) + for (i=0;i<256;i++) { - length = i; - break; + if (order[i] >= 0xFE) + { + length = i; + break; + } } - } // data for Protracker activechan = (0xffffffff >> (32 - header.numchan)) << (32 - header.numchan); @@ -173,71 +158,68 @@ CfmcLoader::load (VFSFile & fd, const CFileProvider & fp) // flags flags = Faust; - rewind (0); + rewind(0); return true; } -float -CfmcLoader::getrefresh () +float CfmcLoader::getrefresh() { return 50.0f; } -std::string CfmcLoader::gettype () +std::string CfmcLoader::gettype() { - return std::string ("Faust Music Creator"); + return std::string("Faust Music Creator"); } -std::string CfmcLoader::gettitle () +std::string CfmcLoader::gettitle() { - return std::string (header.title); + return std::string(header.title); } -std::string CfmcLoader::getinstrument (unsigned int n) +std::string CfmcLoader::getinstrument(unsigned int n) { - return std::string (instruments[n].name); + return std::string(instruments[n].name); } -unsigned int -CfmcLoader::getinstruments () +unsigned int CfmcLoader::getinstruments() { return 32; } /* -------- Private Methods ------------------------------- */ -void -CfmcLoader::buildinst (unsigned char i) +void CfmcLoader::buildinst(unsigned char i) { - inst[i].data[0] = ((instruments[i].synthesis & 1) ^ 1); - inst[i].data[0] |= ((instruments[i].feedback & 7) << 1); - - inst[i].data[3] = ((instruments[i].mod_attack & 15) << 4); - inst[i].data[3] |= (instruments[i].mod_decay & 15); - inst[i].data[5] = ((15 - (instruments[i].mod_sustain & 15)) << 4); - inst[i].data[5] |= (instruments[i].mod_release & 15); - inst[i].data[9] = (63 - (instruments[i].mod_volume & 63)); - inst[i].data[9] |= ((instruments[i].mod_ksl & 3) << 6); - inst[i].data[1] = (instruments[i].mod_freq_multi & 15); - inst[i].data[7] = (instruments[i].mod_waveform & 3); - inst[i].data[1] |= ((instruments[i].mod_sustain_sound & 1) << 5); - inst[i].data[1] |= ((instruments[i].mod_ksr & 1) << 4); - inst[i].data[1] |= ((instruments[i].mod_vibrato & 1) << 6); - inst[i].data[1] |= ((instruments[i].mod_tremolo & 1) << 7); - - inst[i].data[4] = ((instruments[i].car_attack & 15) << 4); - inst[i].data[4] |= (instruments[i].car_decay & 15); - inst[i].data[6] = ((15 - (instruments[i].car_sustain & 15)) << 4); - inst[i].data[6] |= (instruments[i].car_release & 15); - inst[i].data[10] = (63 - (instruments[i].car_volume & 63)); + inst[i].data[0] = ((instruments[i].synthesis & 1) ^ 1); + inst[i].data[0] |= ((instruments[i].feedback & 7) << 1); + + inst[i].data[3] = ((instruments[i].mod_attack & 15) << 4); + inst[i].data[3] |= (instruments[i].mod_decay & 15); + inst[i].data[5] = ((15 - (instruments[i].mod_sustain & 15)) << 4); + inst[i].data[5] |= (instruments[i].mod_release & 15); + inst[i].data[9] = (63 - (instruments[i].mod_volume & 63)); + inst[i].data[9] |= ((instruments[i].mod_ksl & 3) << 6); + inst[i].data[1] = (instruments[i].mod_freq_multi & 15); + inst[i].data[7] = (instruments[i].mod_waveform & 3); + inst[i].data[1] |= ((instruments[i].mod_sustain_sound & 1) << 5); + inst[i].data[1] |= ((instruments[i].mod_ksr & 1) << 4); + inst[i].data[1] |= ((instruments[i].mod_vibrato & 1) << 6); + inst[i].data[1] |= ((instruments[i].mod_tremolo & 1) << 7); + + inst[i].data[4] = ((instruments[i].car_attack & 15) << 4); + inst[i].data[4] |= (instruments[i].car_decay & 15); + inst[i].data[6] = ((15 - (instruments[i].car_sustain & 15)) << 4); + inst[i].data[6] |= (instruments[i].car_release & 15); + inst[i].data[10] = (63 - (instruments[i].car_volume & 63)); inst[i].data[10] |= ((instruments[i].car_ksl & 3) << 6); - inst[i].data[2] = (instruments[i].car_freq_multi & 15); - inst[i].data[8] = (instruments[i].car_waveform & 3); - inst[i].data[2] |= ((instruments[i].car_sustain_sound & 1) << 5); - inst[i].data[2] |= ((instruments[i].car_ksr & 1) << 4); - inst[i].data[2] |= ((instruments[i].car_vibrato & 1) << 6); - inst[i].data[2] |= ((instruments[i].car_tremolo & 1) << 7); - - inst[i].slide = instruments[i].pitch_shift; + inst[i].data[2] = (instruments[i].car_freq_multi & 15); + inst[i].data[8] = (instruments[i].car_waveform & 3); + inst[i].data[2] |= ((instruments[i].car_sustain_sound & 1) << 5); + inst[i].data[2] |= ((instruments[i].car_ksr & 1) << 4); + inst[i].data[2] |= ((instruments[i].car_vibrato & 1) << 6); + inst[i].data[2] |= ((instruments[i].car_tremolo & 1) << 7); + + inst[i].slide = instruments[i].pitch_shift; } diff --git a/src/adplug/core/fmc.h b/src/adplug/core/fmc.h index 3f4eab6..cf148f5 100644 --- a/src/adplug/core/fmc.h +++ b/src/adplug/core/fmc.h @@ -23,69 +23,69 @@ class CfmcLoader: public CmodPlayer { - public: - static CPlayer *factory(Copl *newopl); - - CfmcLoader(Copl *newopl) : CmodPlayer(newopl) { }; - - bool load(VFSFile &fd, const CFileProvider &fp); - float getrefresh(); - - std::string gettype(); - std::string gettitle(); - std::string getinstrument(unsigned int n); - unsigned int getinstruments(); - - private: - - struct fmc_event - { - unsigned char byte0; - unsigned char byte1; - unsigned char byte2; - }; - - struct fmc_header - { - char id[4]; - char title[21]; - unsigned char numchan; - } header; - - struct fmc_instrument - { - unsigned char synthesis; - unsigned char feedback; - - unsigned char mod_attack; - unsigned char mod_decay; - unsigned char mod_sustain; - unsigned char mod_release; - unsigned char mod_volume; - unsigned char mod_ksl; - unsigned char mod_freq_multi; - unsigned char mod_waveform; - unsigned char mod_sustain_sound; - unsigned char mod_ksr; - unsigned char mod_vibrato; - unsigned char mod_tremolo; - unsigned char car_attack; - unsigned char car_decay; - unsigned char car_sustain; - unsigned char car_release; - unsigned char car_volume; - unsigned char car_ksl; - unsigned char car_freq_multi; - unsigned char car_waveform; - unsigned char car_sustain_sound; - unsigned char car_ksr; - unsigned char car_vibrato; - unsigned char car_tremolo; - - signed char pitch_shift; - - char name[21]; - } instruments[32]; - - void buildinst(unsigned char i); + public: + static CPlayer *factory(Copl *newopl); + + CfmcLoader(Copl *newopl) : CmodPlayer(newopl) { }; + + bool load(const std::string &filename, const CFileProvider &fp); + float getrefresh(); + + std::string gettype(); + std::string gettitle(); + std::string getinstrument(unsigned int n); + unsigned int getinstruments(); + + private: + + struct fmc_event + { + unsigned char byte0; + unsigned char byte1; + unsigned char byte2; + }; + + struct fmc_header + { + char id[4]; + char title[21]; + unsigned char numchan; + } header; + + struct fmc_instrument + { + unsigned char synthesis; + unsigned char feedback; + + unsigned char mod_attack; + unsigned char mod_decay; + unsigned char mod_sustain; + unsigned char mod_release; + unsigned char mod_volume; + unsigned char mod_ksl; + unsigned char mod_freq_multi; + unsigned char mod_waveform; + unsigned char mod_sustain_sound; + unsigned char mod_ksr; + unsigned char mod_vibrato; + unsigned char mod_tremolo; + unsigned char car_attack; + unsigned char car_decay; + unsigned char car_sustain; + unsigned char car_release; + unsigned char car_volume; + unsigned char car_ksl; + unsigned char car_freq_multi; + unsigned char car_waveform; + unsigned char car_sustain_sound; + unsigned char car_ksr; + unsigned char car_vibrato; + unsigned char car_tremolo; + + signed char pitch_shift; + + char name[21]; + } instruments[32]; + + void buildinst(unsigned char i); }; diff --git a/src/adplug/core/fmopl.cc b/src/adplug/core/fmopl.cc index 348e51c..9a58f7a 100644 --- a/src/adplug/core/fmopl.cc +++ b/src/adplug/core/fmopl.cc @@ -9,9 +9,9 @@ */ /* - preliminary : - Problem : - note: + preliminary : + Problem : + note: */ /* This version of fmopl.c is a fork of the MAME one, relicensed under the LGPL. @@ -31,14 +31,15 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#define HAS_YM3812 1 +#define INLINE __inline +#define HAS_YM3812 1 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdarg.h> #include <math.h> -//#include "driver.h" /* use M.A.M.E. */ +//#include "driver.h" /* use M.A.M.E. */ #include "fmopl.h" #ifndef PI @@ -48,7 +49,7 @@ /* -------------------- for debug --------------------- */ /* #define OPL_OUTPUT_LOG */ #ifdef OPL_OUTPUT_LOG -static FILE *opl_dbg_fp = nullptr; +static FILE *opl_dbg_fp = NULL; static FM_OPL *opl_dbg_opl[16]; static int opl_dbg_maxchip,opl_dbg_chip; #endif @@ -60,14 +61,14 @@ static int opl_dbg_maxchip,opl_dbg_chip; #define DELTAT_MIXING_LEVEL (1) /* DELTA-T ADPCM MIXING LEVEL */ -#define FREQ_BITS 24 /* frequency turn */ +#define FREQ_BITS 24 /* frequency turn */ /* counter bits = 20 , octerve 7 */ #define FREQ_RATE (1<<(FREQ_BITS-20)) #define TL_BITS (FREQ_BITS+2) /* final output shift , limit minimum and maximum */ -#define OPL_OUTSB (TL_BITS+3-16) /* OPL output final shift 16bit */ +#define OPL_OUTSB (TL_BITS+3-16) /* OPL output final shift 16bit */ #define OPL_MAXOUT (0x7fff<<OPL_OUTSB) #define OPL_MINOUT (-0x8000<<OPL_OUTSB) @@ -115,10 +116,10 @@ static int opl_dbg_maxchip,opl_dbg_chip; /* -------------------- tables --------------------- */ static const int slot_array[32]= { - 0, 2, 4, 1, 3, 5,-1,-1, - 6, 8,10, 7, 9,11,-1,-1, - 12,14,16,13,15,17,-1,-1, - -1,-1,-1,-1,-1,-1,-1,-1 + 0, 2, 4, 1, 3, 5,-1,-1, + 6, 8,10, 7, 9,11,-1,-1, + 12,14,16,13,15,17,-1,-1, + -1,-1,-1,-1,-1,-1,-1,-1 }; /* key scale level */ @@ -127,46 +128,46 @@ static const int slot_array[32]= #define U(x) ((UINT32)(x)) static const UINT32 KSL_TABLE[8*16]= { - /* OCT 0 */ - U( 0.000/DV),U( 0.000/DV),U( 0.000/DV),U( 0.000/DV), - U( 0.000/DV),U( 0.000/DV),U( 0.000/DV),U( 0.000/DV), - U( 0.000/DV),U( 0.000/DV),U( 0.000/DV),U( 0.000/DV), - U( 0.000/DV),U( 0.000/DV),U( 0.000/DV),U( 0.000/DV), - /* OCT 1 */ - U( 0.000/DV),U( 0.000/DV),U( 0.000/DV),U( 0.000/DV), - U( 0.000/DV),U( 0.000/DV),U( 0.000/DV),U( 0.000/DV), - U( 0.000/DV),U( 0.750/DV),U( 1.125/DV),U( 1.500/DV), - U( 1.875/DV),U( 2.250/DV),U( 2.625/DV),U( 3.000/DV), - /* OCT 2 */ - U( 0.000/DV),U( 0.000/DV),U( 0.000/DV),U( 0.000/DV), - U( 0.000/DV),U( 1.125/DV),U( 1.875/DV),U( 2.625/DV), - U( 3.000/DV),U( 3.750/DV),U( 4.125/DV),U( 4.500/DV), - U( 4.875/DV),U( 5.250/DV),U( 5.625/DV),U( 6.000/DV), - /* OCT 3 */ - U( 0.000/DV),U( 0.000/DV),U( 0.000/DV),U( 1.875/DV), - U( 3.000/DV),U( 4.125/DV),U( 4.875/DV),U( 5.625/DV), - U( 6.000/DV),U( 6.750/DV),U( 7.125/DV),U( 7.500/DV), - U( 7.875/DV),U( 8.250/DV),U( 8.625/DV),U( 9.000/DV), - /* OCT 4 */ - U( 0.000/DV),U( 0.000/DV),U( 3.000/DV),U( 4.875/DV), - U( 6.000/DV),U( 7.125/DV),U( 7.875/DV),U( 8.625/DV), - U( 9.000/DV),U( 9.750/DV),U(10.125/DV),U(10.500/DV), - U(10.875/DV),U(11.250/DV),U(11.625/DV),U(12.000/DV), - /* OCT 5 */ - U( 0.000/DV),U( 3.000/DV),U( 6.000/DV),U( 7.875/DV), - U( 9.000/DV),U(10.125/DV),U(10.875/DV),U(11.625/DV), - U(12.000/DV),U(12.750/DV),U(13.125/DV),U(13.500/DV), - U(13.875/DV),U(14.250/DV),U(14.625/DV),U(15.000/DV), - /* OCT 6 */ - U( 0.000/DV),U( 6.000/DV),U( 9.000/DV),U(10.875/DV), - U(12.000/DV),U(13.125/DV),U(13.875/DV),U(14.625/DV), - U(15.000/DV),U(15.750/DV),U(16.125/DV),U(16.500/DV), - U(16.875/DV),U(17.250/DV),U(17.625/DV),U(18.000/DV), - /* OCT 7 */ - U( 0.000/DV),U( 9.000/DV),U(12.000/DV),U(13.875/DV), - U(15.000/DV),U(16.125/DV),U(16.875/DV),U(17.625/DV), - U(18.000/DV),U(18.750/DV),U(19.125/DV),U(19.500/DV), - U(19.875/DV),U(20.250/DV),U(20.625/DV),U(21.000/DV) + /* OCT 0 */ + U( 0.000/DV),U( 0.000/DV),U( 0.000/DV),U( 0.000/DV), + U( 0.000/DV),U( 0.000/DV),U( 0.000/DV),U( 0.000/DV), + U( 0.000/DV),U( 0.000/DV),U( 0.000/DV),U( 0.000/DV), + U( 0.000/DV),U( 0.000/DV),U( 0.000/DV),U( 0.000/DV), + /* OCT 1 */ + U( 0.000/DV),U( 0.000/DV),U( 0.000/DV),U( 0.000/DV), + U( 0.000/DV),U( 0.000/DV),U( 0.000/DV),U( 0.000/DV), + U( 0.000/DV),U( 0.750/DV),U( 1.125/DV),U( 1.500/DV), + U( 1.875/DV),U( 2.250/DV),U( 2.625/DV),U( 3.000/DV), + /* OCT 2 */ + U( 0.000/DV),U( 0.000/DV),U( 0.000/DV),U( 0.000/DV), + U( 0.000/DV),U( 1.125/DV),U( 1.875/DV),U( 2.625/DV), + U( 3.000/DV),U( 3.750/DV),U( 4.125/DV),U( 4.500/DV), + U( 4.875/DV),U( 5.250/DV),U( 5.625/DV),U( 6.000/DV), + /* OCT 3 */ + U( 0.000/DV),U( 0.000/DV),U( 0.000/DV),U( 1.875/DV), + U( 3.000/DV),U( 4.125/DV),U( 4.875/DV),U( 5.625/DV), + U( 6.000/DV),U( 6.750/DV),U( 7.125/DV),U( 7.500/DV), + U( 7.875/DV),U( 8.250/DV),U( 8.625/DV),U( 9.000/DV), + /* OCT 4 */ + U( 0.000/DV),U( 0.000/DV),U( 3.000/DV),U( 4.875/DV), + U( 6.000/DV),U( 7.125/DV),U( 7.875/DV),U( 8.625/DV), + U( 9.000/DV),U( 9.750/DV),U(10.125/DV),U(10.500/DV), + U(10.875/DV),U(11.250/DV),U(11.625/DV),U(12.000/DV), + /* OCT 5 */ + U( 0.000/DV),U( 3.000/DV),U( 6.000/DV),U( 7.875/DV), + U( 9.000/DV),U(10.125/DV),U(10.875/DV),U(11.625/DV), + U(12.000/DV),U(12.750/DV),U(13.125/DV),U(13.500/DV), + U(13.875/DV),U(14.250/DV),U(14.625/DV),U(15.000/DV), + /* OCT 6 */ + U( 0.000/DV),U( 6.000/DV),U( 9.000/DV),U(10.875/DV), + U(12.000/DV),U(13.125/DV),U(13.875/DV),U(14.625/DV), + U(15.000/DV),U(15.750/DV),U(16.125/DV),U(16.500/DV), + U(16.875/DV),U(17.250/DV),U(17.625/DV),U(18.000/DV), + /* OCT 7 */ + U( 0.000/DV),U( 9.000/DV),U(12.000/DV),U(13.875/DV), + U(15.000/DV),U(16.125/DV),U(16.875/DV),U(17.625/DV), + U(18.000/DV),U(18.750/DV),U(19.125/DV),U(19.500/DV), + U(19.875/DV),U(20.250/DV),U(20.625/DV),U(21.000/DV) }; #undef U #undef DV @@ -216,7 +217,7 @@ static INT32 RATE_0[16]= static int num_lock = 0; /* work table */ -static void *cur_chip = nullptr; /* current chip point */ +static void *cur_chip = NULL; /* current chip point */ /* currenct chip state */ /* static OPLSAMPLE *bufL,*bufR; */ static OPL_CH *S_CH; @@ -230,7 +231,7 @@ INT32 *ams_table; INT32 *vib_table; static INT32 amsIncr; static INT32 vibIncr; -static INT32 feedback2; /* connect for SLOT 2 */ +static INT32 feedback2; /* connect for SLOT 2 */ /* log output level */ #define LOG_ERR 3 /* ERROR */ @@ -238,865 +239,863 @@ static INT32 feedback2; /* connect for SLOT 2 */ #define LOG_INF 1 /* INFORMATION */ //#define LOG_LEVEL LOG_INF -#define LOG_LEVEL LOG_ERR +#define LOG_LEVEL LOG_ERR //#define LOG(n,x) if( (n)>=LOG_LEVEL ) logerror x #define LOG(n,x) /* --------------------- subroutines --------------------- */ -static inline int Limit( int val, int max, int min ) { - if ( val > max ) - val = max; - else if ( val < min ) - val = min; +INLINE int Limit( int val, int max, int min ) { + if ( val > max ) + val = max; + else if ( val < min ) + val = min; - return val; + return val; } /* status set and IRQ handling */ -static inline void OPL_STATUS_SET(FM_OPL *OPL,int flag) +INLINE void OPL_STATUS_SET(FM_OPL *OPL,int flag) { - /* set status flag */ - OPL->status |= flag; - if(!(OPL->status & 0x80)) - { - if(OPL->status & OPL->statusmask) - { /* IRQ on */ - OPL->status |= 0x80; - /* callback user interrupt handler (IRQ is OFF to ON) */ - if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,1); - } - } + /* set status flag */ + OPL->status |= flag; + if(!(OPL->status & 0x80)) + { + if(OPL->status & OPL->statusmask) + { /* IRQ on */ + OPL->status |= 0x80; + /* callback user interrupt handler (IRQ is OFF to ON) */ + if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,1); + } + } } /* status reset and IRQ handling */ -static inline void OPL_STATUS_RESET(FM_OPL *OPL,int flag) +INLINE void OPL_STATUS_RESET(FM_OPL *OPL,int flag) { - /* reset status flag */ - OPL->status &=~flag; - if((OPL->status & 0x80)) - { - if (!(OPL->status & OPL->statusmask) ) - { - OPL->status &= 0x7f; - /* callback user interrupt handler (IRQ is ON to OFF) */ - if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,0); - } - } + /* reset status flag */ + OPL->status &=~flag; + if((OPL->status & 0x80)) + { + if (!(OPL->status & OPL->statusmask) ) + { + OPL->status &= 0x7f; + /* callback user interrupt handler (IRQ is ON to OFF) */ + if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,0); + } + } } /* IRQ mask set */ -static inline void OPL_STATUSMASK_SET(FM_OPL *OPL,int flag) +INLINE void OPL_STATUSMASK_SET(FM_OPL *OPL,int flag) { - OPL->statusmask = flag; - /* IRQ handling check */ - OPL_STATUS_SET(OPL,0); - OPL_STATUS_RESET(OPL,0); + OPL->statusmask = flag; + /* IRQ handling check */ + OPL_STATUS_SET(OPL,0); + OPL_STATUS_RESET(OPL,0); } /* ----- key on ----- */ -static inline void OPL_KEYON(OPL_SLOT *SLOT) +INLINE void OPL_KEYON(OPL_SLOT *SLOT) { - /* sin wave restart */ - SLOT->Cnt = 0; - /* set attack */ - SLOT->evm = ENV_MOD_AR; - SLOT->evs = SLOT->evsa; - SLOT->evc = EG_AST; - SLOT->eve = EG_AED; + /* sin wave restart */ + SLOT->Cnt = 0; + /* set attack */ + SLOT->evm = ENV_MOD_AR; + SLOT->evs = SLOT->evsa; + SLOT->evc = EG_AST; + SLOT->eve = EG_AED; } /* ----- key off ----- */ -static inline void OPL_KEYOFF(OPL_SLOT *SLOT) +INLINE void OPL_KEYOFF(OPL_SLOT *SLOT) { - if( SLOT->evm > ENV_MOD_RR) - { - /* set envelope counter from envleope output */ - SLOT->evm = ENV_MOD_RR; - if( !(SLOT->evc&EG_DST) ) - //SLOT->evc = (ENV_CURVE[SLOT->evc>>ENV_BITS]<<ENV_BITS) + EG_DST; - SLOT->evc = EG_DST; - SLOT->eve = EG_DED; - SLOT->evs = SLOT->evsr; - } + if( SLOT->evm > ENV_MOD_RR) + { + /* set envelope counter from envleope output */ + SLOT->evm = ENV_MOD_RR; + if( !(SLOT->evc&EG_DST) ) + //SLOT->evc = (ENV_CURVE[SLOT->evc>>ENV_BITS]<<ENV_BITS) + EG_DST; + SLOT->evc = EG_DST; + SLOT->eve = EG_DED; + SLOT->evs = SLOT->evsr; + } } /* ---------- calcrate Envelope Generator & Phase Generator ---------- */ /* return : envelope output */ -static inline UINT32 OPL_CALC_SLOT( OPL_SLOT *SLOT ) +INLINE UINT32 OPL_CALC_SLOT( OPL_SLOT *SLOT ) { - /* calcrate envelope generator */ - if( (SLOT->evc+=SLOT->evs) >= SLOT->eve ) - { - switch( SLOT->evm ){ - case ENV_MOD_AR: /* ATTACK -> DECAY1 */ - /* next DR */ - SLOT->evm = ENV_MOD_DR; - SLOT->evc = EG_DST; - SLOT->eve = SLOT->SL; - SLOT->evs = SLOT->evsd; - break; - case ENV_MOD_DR: /* DECAY -> SL or RR */ - SLOT->evc = SLOT->SL; - SLOT->eve = EG_DED; - if(SLOT->eg_typ) - { - SLOT->evs = 0; - } - else - { - SLOT->evm = ENV_MOD_RR; - SLOT->evs = SLOT->evsr; - } - break; - case ENV_MOD_RR: /* RR -> OFF */ - SLOT->evc = EG_OFF; - SLOT->eve = EG_OFF+1; - SLOT->evs = 0; - break; - } - } - /* calcrate envelope */ - return SLOT->TLL+ENV_CURVE[SLOT->evc>>ENV_BITS]+(SLOT->ams ? ams : 0); + /* calcrate envelope generator */ + if( (SLOT->evc+=SLOT->evs) >= SLOT->eve ) + { + switch( SLOT->evm ){ + case ENV_MOD_AR: /* ATTACK -> DECAY1 */ + /* next DR */ + SLOT->evm = ENV_MOD_DR; + SLOT->evc = EG_DST; + SLOT->eve = SLOT->SL; + SLOT->evs = SLOT->evsd; + break; + case ENV_MOD_DR: /* DECAY -> SL or RR */ + SLOT->evc = SLOT->SL; + SLOT->eve = EG_DED; + if(SLOT->eg_typ) + { + SLOT->evs = 0; + } + else + { + SLOT->evm = ENV_MOD_RR; + SLOT->evs = SLOT->evsr; + } + break; + case ENV_MOD_RR: /* RR -> OFF */ + SLOT->evc = EG_OFF; + SLOT->eve = EG_OFF+1; + SLOT->evs = 0; + break; + } + } + /* calcrate envelope */ + return SLOT->TLL+ENV_CURVE[SLOT->evc>>ENV_BITS]+(SLOT->ams ? ams : 0); } /* set algorythm connection */ static void set_algorythm( OPL_CH *CH) { - INT32 *carrier = &outd[0]; - CH->connect1 = CH->CON ? carrier : &feedback2; - CH->connect2 = carrier; + INT32 *carrier = &outd[0]; + CH->connect1 = CH->CON ? carrier : &feedback2; + CH->connect2 = carrier; } /* ---------- frequency counter for operater update ---------- */ -static inline void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT) +INLINE void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT) { - int ksr; - - /* frequency step counter */ - SLOT->Incr = CH->fc * SLOT->mul; - ksr = CH->kcode >> SLOT->KSR; - - if( SLOT->ksr != ksr ) - { - SLOT->ksr = ksr; - /* attack , decay rate recalcration */ - SLOT->evsa = SLOT->AR[ksr]; - SLOT->evsd = SLOT->DR[ksr]; - SLOT->evsr = SLOT->RR[ksr]; - } - SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl); + int ksr; + + /* frequency step counter */ + SLOT->Incr = CH->fc * SLOT->mul; + ksr = CH->kcode >> SLOT->KSR; + + if( SLOT->ksr != ksr ) + { + SLOT->ksr = ksr; + /* attack , decay rate recalcration */ + SLOT->evsa = SLOT->AR[ksr]; + SLOT->evsd = SLOT->DR[ksr]; + SLOT->evsr = SLOT->RR[ksr]; + } + SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl); } /* set multi,am,vib,EG-TYP,KSR,mul */ -static inline void set_mul(FM_OPL *OPL,int slot,int v) +INLINE void set_mul(FM_OPL *OPL,int slot,int v) { - OPL_CH *CH = &OPL->P_CH[slot/2]; - OPL_SLOT *SLOT = &CH->SLOT[slot&1]; - - SLOT->mul = MUL_TABLE[v&0x0f]; - SLOT->KSR = (v&0x10) ? 0 : 2; - SLOT->eg_typ = (v&0x20)>>5; - SLOT->vib = (v&0x40); - SLOT->ams = (v&0x80); - CALC_FCSLOT(CH,SLOT); + OPL_CH *CH = &OPL->P_CH[slot/2]; + OPL_SLOT *SLOT = &CH->SLOT[slot&1]; + + SLOT->mul = MUL_TABLE[v&0x0f]; + SLOT->KSR = (v&0x10) ? 0 : 2; + SLOT->eg_typ = (v&0x20)>>5; + SLOT->vib = (v&0x40); + SLOT->ams = (v&0x80); + CALC_FCSLOT(CH,SLOT); } /* set ksl & tl */ -static inline void set_ksl_tl(FM_OPL *OPL,int slot,int v) +INLINE void set_ksl_tl(FM_OPL *OPL,int slot,int v) { - OPL_CH *CH = &OPL->P_CH[slot/2]; - OPL_SLOT *SLOT = &CH->SLOT[slot&1]; - int ksl = v>>6; /* 0 / 1.5 / 3 / 6 db/OCT */ + OPL_CH *CH = &OPL->P_CH[slot/2]; + OPL_SLOT *SLOT = &CH->SLOT[slot&1]; + int ksl = v>>6; /* 0 / 1.5 / 3 / 6 db/OCT */ - SLOT->ksl = ksl ? 3-ksl : 31; - SLOT->TL = (v&0x3f)*(0.75/EG_STEP); /* 0.75db step */ + SLOT->ksl = ksl ? 3-ksl : 31; + SLOT->TL = (v&0x3f)*(0.75/EG_STEP); /* 0.75db step */ - if( !(OPL->mode&0x80) ) - { /* not CSM latch total level */ - SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl); - } + if( !(OPL->mode&0x80) ) + { /* not CSM latch total level */ + SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl); + } } /* set attack rate & decay rate */ -static inline void set_ar_dr(FM_OPL *OPL,int slot,int v) +INLINE void set_ar_dr(FM_OPL *OPL,int slot,int v) { - OPL_CH *CH = &OPL->P_CH[slot/2]; - OPL_SLOT *SLOT = &CH->SLOT[slot&1]; - int ar = v>>4; - int dr = v&0x0f; - - SLOT->AR = ar ? &OPL->AR_TABLE[ar<<2] : RATE_0; - SLOT->evsa = SLOT->AR[SLOT->ksr]; - if( SLOT->evm == ENV_MOD_AR ) SLOT->evs = SLOT->evsa; - - SLOT->DR = dr ? &OPL->DR_TABLE[dr<<2] : RATE_0; - SLOT->evsd = SLOT->DR[SLOT->ksr]; - if( SLOT->evm == ENV_MOD_DR ) SLOT->evs = SLOT->evsd; + OPL_CH *CH = &OPL->P_CH[slot/2]; + OPL_SLOT *SLOT = &CH->SLOT[slot&1]; + int ar = v>>4; + int dr = v&0x0f; + + SLOT->AR = ar ? &OPL->AR_TABLE[ar<<2] : RATE_0; + SLOT->evsa = SLOT->AR[SLOT->ksr]; + if( SLOT->evm == ENV_MOD_AR ) SLOT->evs = SLOT->evsa; + + SLOT->DR = dr ? &OPL->DR_TABLE[dr<<2] : RATE_0; + SLOT->evsd = SLOT->DR[SLOT->ksr]; + if( SLOT->evm == ENV_MOD_DR ) SLOT->evs = SLOT->evsd; } /* set sustain level & release rate */ -static inline void set_sl_rr(FM_OPL *OPL,int slot,int v) +INLINE void set_sl_rr(FM_OPL *OPL,int slot,int v) { - OPL_CH *CH = &OPL->P_CH[slot/2]; - OPL_SLOT *SLOT = &CH->SLOT[slot&1]; - int sl = v>>4; - int rr = v & 0x0f; - - SLOT->SL = SL_TABLE[sl]; - if( SLOT->evm == ENV_MOD_DR ) SLOT->eve = SLOT->SL; - SLOT->RR = &OPL->DR_TABLE[rr<<2]; - SLOT->evsr = SLOT->RR[SLOT->ksr]; - if( SLOT->evm == ENV_MOD_RR ) SLOT->evs = SLOT->evsr; + OPL_CH *CH = &OPL->P_CH[slot/2]; + OPL_SLOT *SLOT = &CH->SLOT[slot&1]; + int sl = v>>4; + int rr = v & 0x0f; + + SLOT->SL = SL_TABLE[sl]; + if( SLOT->evm == ENV_MOD_DR ) SLOT->eve = SLOT->SL; + SLOT->RR = &OPL->DR_TABLE[rr<<2]; + SLOT->evsr = SLOT->RR[SLOT->ksr]; + if( SLOT->evm == ENV_MOD_RR ) SLOT->evs = SLOT->evsr; } /* operator output calcrator */ #define OP_OUT(slot,env,con) slot->wavetable[((slot->Cnt+con)/(0x1000000/SIN_ENT))&(SIN_ENT-1)][env] /* ---------- calcrate one of channel ---------- */ -static inline void OPL_CALC_CH( OPL_CH *CH ) +INLINE void OPL_CALC_CH( OPL_CH *CH ) { - UINT32 env_out; - OPL_SLOT *SLOT; - - feedback2 = 0; - /* SLOT 1 */ - SLOT = &CH->SLOT[SLOT1]; - env_out=OPL_CALC_SLOT(SLOT); - if( env_out < EG_ENT-1 ) - { - /* PG */ - if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE); - else SLOT->Cnt += SLOT->Incr; - /* connectoion */ - if(CH->FB) - { - int feedback1 = (CH->op1_out[0]+CH->op1_out[1])>>CH->FB; - CH->op1_out[1] = CH->op1_out[0]; - *CH->connect1 += CH->op1_out[0] = OP_OUT(SLOT,env_out,feedback1); - } - else - { - *CH->connect1 += OP_OUT(SLOT,env_out,0); - } - }else - { - CH->op1_out[1] = CH->op1_out[0]; - CH->op1_out[0] = 0; - } - /* SLOT 2 */ - SLOT = &CH->SLOT[SLOT2]; - env_out=OPL_CALC_SLOT(SLOT); - if( env_out < EG_ENT-1 ) - { - /* PG */ - if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE); - else SLOT->Cnt += SLOT->Incr; - /* connectoion */ - outd[0] += OP_OUT(SLOT,env_out, feedback2); - } + UINT32 env_out; + OPL_SLOT *SLOT; + + feedback2 = 0; + /* SLOT 1 */ + SLOT = &CH->SLOT[SLOT1]; + env_out=OPL_CALC_SLOT(SLOT); + if( env_out < EG_ENT-1 ) + { + /* PG */ + if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE); + else SLOT->Cnt += SLOT->Incr; + /* connectoion */ + if(CH->FB) + { + int feedback1 = (CH->op1_out[0]+CH->op1_out[1])>>CH->FB; + CH->op1_out[1] = CH->op1_out[0]; + *CH->connect1 += CH->op1_out[0] = OP_OUT(SLOT,env_out,feedback1); + } + else + { + *CH->connect1 += OP_OUT(SLOT,env_out,0); + } + }else + { + CH->op1_out[1] = CH->op1_out[0]; + CH->op1_out[0] = 0; + } + /* SLOT 2 */ + SLOT = &CH->SLOT[SLOT2]; + env_out=OPL_CALC_SLOT(SLOT); + if( env_out < EG_ENT-1 ) + { + /* PG */ + if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE); + else SLOT->Cnt += SLOT->Incr; + /* connectoion */ + outd[0] += OP_OUT(SLOT,env_out, feedback2); + } } /* ---------- calcrate rythm block ---------- */ #define WHITE_NOISE_db 6.0 -static inline void OPL_CALC_RH( OPL_CH *CH ) +INLINE void OPL_CALC_RH( OPL_CH *CH ) { - UINT32 env_tam,env_sd,env_top,env_hh; - int whitenoise = (rand()&1)*(WHITE_NOISE_db/EG_STEP); - INT32 tone8; - - OPL_SLOT *SLOT; - int env_out; - - /* BD : same as FM serial mode and output level is large */ - feedback2 = 0; - /* SLOT 1 */ - SLOT = &CH[6].SLOT[SLOT1]; - env_out=OPL_CALC_SLOT(SLOT); - if( env_out < EG_ENT-1 ) - { - /* PG */ - if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE); - else SLOT->Cnt += SLOT->Incr; - /* connectoion */ - if(CH[6].FB) - { - int feedback1 = (CH[6].op1_out[0]+CH[6].op1_out[1])>>CH[6].FB; - CH[6].op1_out[1] = CH[6].op1_out[0]; - feedback2 = CH[6].op1_out[0] = OP_OUT(SLOT,env_out,feedback1); - } - else - { - feedback2 = OP_OUT(SLOT,env_out,0); - } - }else - { - feedback2 = 0; - CH[6].op1_out[1] = CH[6].op1_out[0]; - CH[6].op1_out[0] = 0; - } - /* SLOT 2 */ - SLOT = &CH[6].SLOT[SLOT2]; - env_out=OPL_CALC_SLOT(SLOT); - if( env_out < EG_ENT-1 ) - { - /* PG */ - if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE); - else SLOT->Cnt += SLOT->Incr; - /* connectoion */ - outd[0] += OP_OUT(SLOT,env_out, feedback2)*2; - } - - // SD (17) = mul14[fnum7] + white noise - // TAM (15) = mul15[fnum8] - // TOP (18) = fnum6(mul18[fnum8]+whitenoise) - // HH (14) = fnum7(mul18[fnum8]+whitenoise) + white noise - env_sd =OPL_CALC_SLOT(SLOT7_2) + whitenoise; - env_tam=OPL_CALC_SLOT(SLOT8_1); - env_top=OPL_CALC_SLOT(SLOT8_2); - env_hh =OPL_CALC_SLOT(SLOT7_1) + whitenoise; - - /* PG */ - if(SLOT7_1->vib) SLOT7_1->Cnt += (2*SLOT7_1->Incr*vib/VIB_RATE); - else SLOT7_1->Cnt += 2*SLOT7_1->Incr; - if(SLOT7_2->vib) SLOT7_2->Cnt += ((CH[7].fc*8)*vib/VIB_RATE); - else SLOT7_2->Cnt += (CH[7].fc*8); - if(SLOT8_1->vib) SLOT8_1->Cnt += (SLOT8_1->Incr*vib/VIB_RATE); - else SLOT8_1->Cnt += SLOT8_1->Incr; - if(SLOT8_2->vib) SLOT8_2->Cnt += ((CH[8].fc*48)*vib/VIB_RATE); - else SLOT8_2->Cnt += (CH[8].fc*48); - - tone8 = OP_OUT(SLOT8_2,whitenoise,0 ); - - /* SD */ - if( env_sd < EG_ENT-1 ) - outd[0] += OP_OUT(SLOT7_1,env_sd, 0)*8; - /* TAM */ - if( env_tam < EG_ENT-1 ) - outd[0] += OP_OUT(SLOT8_1,env_tam, 0)*2; - /* TOP-CY */ - if( env_top < EG_ENT-1 ) - outd[0] += OP_OUT(SLOT7_2,env_top,tone8)*2; - /* HH */ - if( env_hh < EG_ENT-1 ) - outd[0] += OP_OUT(SLOT7_2,env_hh,tone8)*2; + UINT32 env_tam,env_sd,env_top,env_hh; + int whitenoise = (rand()&1)*(WHITE_NOISE_db/EG_STEP); + INT32 tone8; + + OPL_SLOT *SLOT; + int env_out; + + /* BD : same as FM serial mode and output level is large */ + feedback2 = 0; + /* SLOT 1 */ + SLOT = &CH[6].SLOT[SLOT1]; + env_out=OPL_CALC_SLOT(SLOT); + if( env_out < EG_ENT-1 ) + { + /* PG */ + if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE); + else SLOT->Cnt += SLOT->Incr; + /* connectoion */ + if(CH[6].FB) + { + int feedback1 = (CH[6].op1_out[0]+CH[6].op1_out[1])>>CH[6].FB; + CH[6].op1_out[1] = CH[6].op1_out[0]; + feedback2 = CH[6].op1_out[0] = OP_OUT(SLOT,env_out,feedback1); + } + else + { + feedback2 = OP_OUT(SLOT,env_out,0); + } + }else + { + feedback2 = 0; + CH[6].op1_out[1] = CH[6].op1_out[0]; + CH[6].op1_out[0] = 0; + } + /* SLOT 2 */ + SLOT = &CH[6].SLOT[SLOT2]; + env_out=OPL_CALC_SLOT(SLOT); + if( env_out < EG_ENT-1 ) + { + /* PG */ + if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE); + else SLOT->Cnt += SLOT->Incr; + /* connectoion */ + outd[0] += OP_OUT(SLOT,env_out, feedback2)*2; + } + + // SD (17) = mul14[fnum7] + white noise + // TAM (15) = mul15[fnum8] + // TOP (18) = fnum6(mul18[fnum8]+whitenoise) + // HH (14) = fnum7(mul18[fnum8]+whitenoise) + white noise + env_sd =OPL_CALC_SLOT(SLOT7_2) + whitenoise; + env_tam=OPL_CALC_SLOT(SLOT8_1); + env_top=OPL_CALC_SLOT(SLOT8_2); + env_hh =OPL_CALC_SLOT(SLOT7_1) + whitenoise; + + /* PG */ + if(SLOT7_1->vib) SLOT7_1->Cnt += (2*SLOT7_1->Incr*vib/VIB_RATE); + else SLOT7_1->Cnt += 2*SLOT7_1->Incr; + if(SLOT7_2->vib) SLOT7_2->Cnt += ((CH[7].fc*8)*vib/VIB_RATE); + else SLOT7_2->Cnt += (CH[7].fc*8); + if(SLOT8_1->vib) SLOT8_1->Cnt += (SLOT8_1->Incr*vib/VIB_RATE); + else SLOT8_1->Cnt += SLOT8_1->Incr; + if(SLOT8_2->vib) SLOT8_2->Cnt += ((CH[8].fc*48)*vib/VIB_RATE); + else SLOT8_2->Cnt += (CH[8].fc*48); + + tone8 = OP_OUT(SLOT8_2,whitenoise,0 ); + + /* SD */ + if( env_sd < EG_ENT-1 ) + outd[0] += OP_OUT(SLOT7_1,env_sd, 0)*8; + /* TAM */ + if( env_tam < EG_ENT-1 ) + outd[0] += OP_OUT(SLOT8_1,env_tam, 0)*2; + /* TOP-CY */ + if( env_top < EG_ENT-1 ) + outd[0] += OP_OUT(SLOT7_2,env_top,tone8)*2; + /* HH */ + if( env_hh < EG_ENT-1 ) + outd[0] += OP_OUT(SLOT7_2,env_hh,tone8)*2; } /* ----------- initialize time tabls ----------- */ static void init_timetables( FM_OPL *OPL , int ARRATE , int DRRATE ) { - int i; - double rate; - - /* make attack rate & decay rate tables */ - for (i = 0;i < 4;i++) OPL->AR_TABLE[i] = OPL->DR_TABLE[i] = 0; - for (i = 4;i <= 60;i++){ - rate = OPL->freqbase; /* frequency rate */ - if( i < 60 ) rate *= 1.0+(i&3)*0.25; /* b0-1 : x1 , x1.25 , x1.5 , x1.75 */ - rate *= 1<<((i>>2)-1); /* b2-5 : shift bit */ - rate *= (double)(EG_ENT<<ENV_BITS); - OPL->AR_TABLE[i] = rate / ARRATE; - OPL->DR_TABLE[i] = rate / DRRATE; - } - // FIXME: warning: iteration 15u invokes undefined behavior - // for (i = 60; i < 76; i++) - for (i = 60; i < 75; i++) - { - OPL->AR_TABLE[i] = EG_AED-1; - OPL->DR_TABLE[i] = OPL->DR_TABLE[60]; - } + int i; + double rate; + + /* make attack rate & decay rate tables */ + for (i = 0;i < 4;i++) OPL->AR_TABLE[i] = OPL->DR_TABLE[i] = 0; + for (i = 4;i <= 60;i++){ + rate = OPL->freqbase; /* frequency rate */ + if( i < 60 ) rate *= 1.0+(i&3)*0.25; /* b0-1 : x1 , x1.25 , x1.5 , x1.75 */ + rate *= 1<<((i>>2)-1); /* b2-5 : shift bit */ + rate *= (double)(EG_ENT<<ENV_BITS); + OPL->AR_TABLE[i] = rate / ARRATE; + OPL->DR_TABLE[i] = rate / DRRATE; + } + for (i = 60;i < 75;i++) + { + OPL->AR_TABLE[i] = EG_AED-1; + OPL->DR_TABLE[i] = OPL->DR_TABLE[60]; + } #if 0 - for (i = 0;i < 64 ;i++){ /* make for overflow area */ - LOG(LOG_WAR,("rate %2d , ar %f ms , dr %f ms \n",i, - ((double)(EG_ENT<<ENV_BITS) / OPL->AR_TABLE[i]) * (1000.0 / OPL->rate), - ((double)(EG_ENT<<ENV_BITS) / OPL->DR_TABLE[i]) * (1000.0 / OPL->rate) )); - } + for (i = 0;i < 64 ;i++){ /* make for overflow area */ + LOG(LOG_WAR,("rate %2d , ar %f ms , dr %f ms \n",i, + ((double)(EG_ENT<<ENV_BITS) / OPL->AR_TABLE[i]) * (1000.0 / OPL->rate), + ((double)(EG_ENT<<ENV_BITS) / OPL->DR_TABLE[i]) * (1000.0 / OPL->rate) )); + } #endif } /* ---------- generic table initialize ---------- */ static int OPLOpenTable( void ) { - int s,t; - double rate; - int i,j; - double pom; - - /* allocate dynamic tables */ - if( (TL_TABLE = (INT32*)malloc(TL_MAX*2*sizeof(INT32))) == nullptr) - return 0; - if( (SIN_TABLE = (INT32**)malloc(SIN_ENT*4 *sizeof(INT32 *))) == nullptr) - { - free(TL_TABLE); - return 0; - } - if( (AMS_TABLE = (INT32*)malloc(AMS_ENT*2 *sizeof(INT32))) == nullptr) - { - free(TL_TABLE); - free(SIN_TABLE); - return 0; - } - if( (VIB_TABLE = (INT32*)malloc(VIB_ENT*2 *sizeof(INT32))) == nullptr) - { - free(TL_TABLE); - free(SIN_TABLE); - free(AMS_TABLE); - return 0; - } - /* make total level table */ - for (t = 0;t < EG_ENT-1 ;t++){ - rate = ((1<<TL_BITS)-1)/pow(10,EG_STEP*t/20); /* dB -> voltage */ - TL_TABLE[ t] = (int)rate; - TL_TABLE[TL_MAX+t] = -TL_TABLE[t]; -/* LOG(LOG_INF,("TotalLevel(%3d) = %x\n",t,TL_TABLE[t]));*/ - } - /* fill volume off area */ - for ( t = EG_ENT-1; t < TL_MAX ;t++){ - TL_TABLE[t] = TL_TABLE[TL_MAX+t] = 0; - } - - /* make sinwave table (total level offet) */ - /* degree 0 = degree 180 = off */ - SIN_TABLE[0] = SIN_TABLE[SIN_ENT/2] = &TL_TABLE[EG_ENT-1]; - for (s = 1;s <= SIN_ENT/4;s++){ - pom = sin(2*PI*s/SIN_ENT); /* sin */ - pom = 20*log10(1/pom); /* decibel */ - j = pom / EG_STEP; /* TL_TABLE steps */ + int s,t; + double rate; + int i,j; + double pom; + + /* allocate dynamic tables */ + if( (TL_TABLE = (INT32*)malloc(TL_MAX*2*sizeof(INT32))) == NULL) + return 0; + if( (SIN_TABLE = (INT32**)malloc(SIN_ENT*4 *sizeof(INT32 *))) == NULL) + { + free(TL_TABLE); + return 0; + } + if( (AMS_TABLE = (INT32*)malloc(AMS_ENT*2 *sizeof(INT32))) == NULL) + { + free(TL_TABLE); + free(SIN_TABLE); + return 0; + } + if( (VIB_TABLE = (INT32*)malloc(VIB_ENT*2 *sizeof(INT32))) == NULL) + { + free(TL_TABLE); + free(SIN_TABLE); + free(AMS_TABLE); + return 0; + } + /* make total level table */ + for (t = 0;t < EG_ENT-1 ;t++){ + rate = ((1<<TL_BITS)-1)/pow(10,EG_STEP*t/20); /* dB -> voltage */ + TL_TABLE[ t] = (int)rate; + TL_TABLE[TL_MAX+t] = -TL_TABLE[t]; +/* LOG(LOG_INF,("TotalLevel(%3d) = %x\n",t,TL_TABLE[t]));*/ + } + /* fill volume off area */ + for ( t = EG_ENT-1; t < TL_MAX ;t++){ + TL_TABLE[t] = TL_TABLE[TL_MAX+t] = 0; + } + + /* make sinwave table (total level offet) */ + /* degree 0 = degree 180 = off */ + SIN_TABLE[0] = SIN_TABLE[SIN_ENT/2] = &TL_TABLE[EG_ENT-1]; + for (s = 1;s <= SIN_ENT/4;s++){ + pom = sin(2*PI*s/SIN_ENT); /* sin */ + pom = 20*log10(1/pom); /* decibel */ + j = pom / EG_STEP; /* TL_TABLE steps */ /* degree 0 - 90 , degree 180 - 90 : plus section */ - SIN_TABLE[ s] = SIN_TABLE[SIN_ENT/2-s] = &TL_TABLE[j]; + SIN_TABLE[ s] = SIN_TABLE[SIN_ENT/2-s] = &TL_TABLE[j]; /* degree 180 - 270 , degree 360 - 270 : minus section */ - SIN_TABLE[SIN_ENT/2+s] = SIN_TABLE[SIN_ENT -s] = &TL_TABLE[TL_MAX+j]; -/* LOG(LOG_INF,("sin(%3d) = %f:%f db\n",s,pom,(double)j * EG_STEP));*/ - } - for (s = 0;s < SIN_ENT;s++) - { - SIN_TABLE[SIN_ENT*1+s] = s<(SIN_ENT/2) ? SIN_TABLE[s] : &TL_TABLE[EG_ENT]; - SIN_TABLE[SIN_ENT*2+s] = SIN_TABLE[s % (SIN_ENT/2)]; - SIN_TABLE[SIN_ENT*3+s] = (s/(SIN_ENT/4))&1 ? &TL_TABLE[EG_ENT] : SIN_TABLE[SIN_ENT*2+s]; - } - - /* envelope counter -> envelope output table */ - for (i=0; i<EG_ENT; i++) - { - /* ATTACK curve */ - pom = pow( ((double)(EG_ENT-1-i)/EG_ENT) , 8 ) * EG_ENT; - /* if( pom >= EG_ENT ) pom = EG_ENT-1; */ - ENV_CURVE[i] = (int)pom; - /* DECAY ,RELEASE curve */ - ENV_CURVE[(EG_DST>>ENV_BITS)+i]= i; - } - /* off */ - ENV_CURVE[EG_OFF>>ENV_BITS]= EG_ENT-1; - /* make LFO ams table */ - for (i=0; i<AMS_ENT; i++) - { - pom = (1.0+sin(2*PI*i/AMS_ENT))/2; /* sin */ - AMS_TABLE[i] = (1.0/EG_STEP)*pom; /* 1dB */ - AMS_TABLE[AMS_ENT+i] = (4.8/EG_STEP)*pom; /* 4.8dB */ - } - /* make LFO vibrate table */ - for (i=0; i<VIB_ENT; i++) - { - /* 100cent = 1seminote = 6% ?? */ - pom = (double)VIB_RATE*0.06*sin(2*PI*i/VIB_ENT); /* +-100sect step */ - VIB_TABLE[i] = VIB_RATE + (pom*0.07); /* +- 7cent */ - VIB_TABLE[VIB_ENT+i] = VIB_RATE + (pom*0.14); /* +-14cent */ - /* LOG(LOG_INF,("vib %d=%d\n",i,VIB_TABLE[VIB_ENT+i])); */ - } - return 1; + SIN_TABLE[SIN_ENT/2+s] = SIN_TABLE[SIN_ENT -s] = &TL_TABLE[TL_MAX+j]; +/* LOG(LOG_INF,("sin(%3d) = %f:%f db\n",s,pom,(double)j * EG_STEP));*/ + } + for (s = 0;s < SIN_ENT;s++) + { + SIN_TABLE[SIN_ENT*1+s] = s<(SIN_ENT/2) ? SIN_TABLE[s] : &TL_TABLE[EG_ENT]; + SIN_TABLE[SIN_ENT*2+s] = SIN_TABLE[s % (SIN_ENT/2)]; + SIN_TABLE[SIN_ENT*3+s] = (s/(SIN_ENT/4))&1 ? &TL_TABLE[EG_ENT] : SIN_TABLE[SIN_ENT*2+s]; + } + + /* envelope counter -> envelope output table */ + for (i=0; i<EG_ENT; i++) + { + /* ATTACK curve */ + pom = pow( ((double)(EG_ENT-1-i)/EG_ENT) , 8 ) * EG_ENT; + /* if( pom >= EG_ENT ) pom = EG_ENT-1; */ + ENV_CURVE[i] = (int)pom; + /* DECAY ,RELEASE curve */ + ENV_CURVE[(EG_DST>>ENV_BITS)+i]= i; + } + /* off */ + ENV_CURVE[EG_OFF>>ENV_BITS]= EG_ENT-1; + /* make LFO ams table */ + for (i=0; i<AMS_ENT; i++) + { + pom = (1.0+sin(2*PI*i/AMS_ENT))/2; /* sin */ + AMS_TABLE[i] = (1.0/EG_STEP)*pom; /* 1dB */ + AMS_TABLE[AMS_ENT+i] = (4.8/EG_STEP)*pom; /* 4.8dB */ + } + /* make LFO vibrate table */ + for (i=0; i<VIB_ENT; i++) + { + /* 100cent = 1seminote = 6% ?? */ + pom = (double)VIB_RATE*0.06*sin(2*PI*i/VIB_ENT); /* +-100sect step */ + VIB_TABLE[i] = VIB_RATE + (pom*0.07); /* +- 7cent */ + VIB_TABLE[VIB_ENT+i] = VIB_RATE + (pom*0.14); /* +-14cent */ + /* LOG(LOG_INF,("vib %d=%d\n",i,VIB_TABLE[VIB_ENT+i])); */ + } + return 1; } static void OPLCloseTable( void ) { - free(TL_TABLE); - free(SIN_TABLE); - free(AMS_TABLE); - free(VIB_TABLE); + free(TL_TABLE); + free(SIN_TABLE); + free(AMS_TABLE); + free(VIB_TABLE); } /* CSM Key Controll */ -static inline void CSMKeyControll(OPL_CH *CH) +INLINE void CSMKeyControll(OPL_CH *CH) { - OPL_SLOT *slot1 = &CH->SLOT[SLOT1]; - OPL_SLOT *slot2 = &CH->SLOT[SLOT2]; - /* all key off */ - OPL_KEYOFF(slot1); - OPL_KEYOFF(slot2); - /* total level latch */ - slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl); - slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl); - /* key on */ - CH->op1_out[0] = CH->op1_out[1] = 0; - OPL_KEYON(slot1); - OPL_KEYON(slot2); + OPL_SLOT *slot1 = &CH->SLOT[SLOT1]; + OPL_SLOT *slot2 = &CH->SLOT[SLOT2]; + /* all key off */ + OPL_KEYOFF(slot1); + OPL_KEYOFF(slot2); + /* total level latch */ + slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl); + slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl); + /* key on */ + CH->op1_out[0] = CH->op1_out[1] = 0; + OPL_KEYON(slot1); + OPL_KEYON(slot2); } /* ---------- opl initialize ---------- */ static void OPL_initalize(FM_OPL *OPL) { - int fn; - - /* frequency base */ - OPL->freqbase = (OPL->rate) ? ((double)OPL->clock / OPL->rate) / 72 : 0; - /* Timer base time */ - OPL->TimerBase = 1.0/((double)OPL->clock / 72.0 ); - /* make time tables */ - init_timetables( OPL , OPL_ARRATE , OPL_DRRATE ); - /* make fnumber -> increment counter table */ - for( fn=0 ; fn < 1024 ; fn++ ) - { - OPL->FN_TABLE[fn] = OPL->freqbase * fn * FREQ_RATE * (1<<7) / 2; - } - /* LFO freq.table */ - OPL->amsIncr = OPL->rate ? (double)AMS_ENT*(1<<AMS_SHIFT) / OPL->rate * 3.7 * ((double)OPL->clock/3600000) : 0; - OPL->vibIncr = OPL->rate ? (double)VIB_ENT*(1<<VIB_SHIFT) / OPL->rate * 6.4 * ((double)OPL->clock/3600000) : 0; + int fn; + + /* frequency base */ + OPL->freqbase = (OPL->rate) ? ((double)OPL->clock / OPL->rate) / 72 : 0; + /* Timer base time */ + OPL->TimerBase = 1.0/((double)OPL->clock / 72.0 ); + /* make time tables */ + init_timetables( OPL , OPL_ARRATE , OPL_DRRATE ); + /* make fnumber -> increment counter table */ + for( fn=0 ; fn < 1024 ; fn++ ) + { + OPL->FN_TABLE[fn] = OPL->freqbase * fn * FREQ_RATE * (1<<7) / 2; + } + /* LFO freq.table */ + OPL->amsIncr = OPL->rate ? (double)AMS_ENT*(1<<AMS_SHIFT) / OPL->rate * 3.7 * ((double)OPL->clock/3600000) : 0; + OPL->vibIncr = OPL->rate ? (double)VIB_ENT*(1<<VIB_SHIFT) / OPL->rate * 6.4 * ((double)OPL->clock/3600000) : 0; } /* ---------- write a OPL registers ---------- */ static void OPLWriteReg(FM_OPL *OPL, int r, int v) { - OPL_CH *CH; - int slot; - int block_fnum; - - switch(r&0xe0) - { - case 0x00: /* 00-1f:controll */ - switch(r&0x1f) - { - case 0x01: - /* wave selector enable */ - if(OPL->type&OPL_TYPE_WAVESEL) - { - OPL->wavesel = v&0x20; - if(!OPL->wavesel) - { - /* preset compatible mode */ - int c; - for(c=0;c<OPL->max_ch;c++) - { - OPL->P_CH[c].SLOT[SLOT1].wavetable = &SIN_TABLE[0]; - OPL->P_CH[c].SLOT[SLOT2].wavetable = &SIN_TABLE[0]; - } - } - } - return; - case 0x02: /* Timer 1 */ - OPL->T[0] = (256-v)*4; - break; - case 0x03: /* Timer 2 */ - OPL->T[1] = (256-v)*16; - return; - case 0x04: /* IRQ clear / mask and Timer enable */ - if(v&0x80) - { /* IRQ flag clear */ - OPL_STATUS_RESET(OPL,0x7f); - } - else - { /* set IRQ mask ,timer enable*/ - UINT8 st1 = v&1; - UINT8 st2 = (v>>1)&1; - /* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */ - OPL_STATUS_RESET(OPL,v&0x78); - OPL_STATUSMASK_SET(OPL,((~v)&0x78)|0x01); - /* timer 2 */ - if(OPL->st[1] != st2) - { - double interval = st2 ? (double)OPL->T[1]*OPL->TimerBase : 0.0; - OPL->st[1] = st2; - if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+1,interval); - } - /* timer 1 */ - if(OPL->st[0] != st1) - { - double interval = st1 ? (double)OPL->T[0]*OPL->TimerBase : 0.0; - OPL->st[0] = st1; - if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+0,interval); - } - } - return; + OPL_CH *CH; + int slot; + int block_fnum; + + switch(r&0xe0) + { + case 0x00: /* 00-1f:controll */ + switch(r&0x1f) + { + case 0x01: + /* wave selector enable */ + if(OPL->type&OPL_TYPE_WAVESEL) + { + OPL->wavesel = v&0x20; + if(!OPL->wavesel) + { + /* preset compatible mode */ + int c; + for(c=0;c<OPL->max_ch;c++) + { + OPL->P_CH[c].SLOT[SLOT1].wavetable = &SIN_TABLE[0]; + OPL->P_CH[c].SLOT[SLOT2].wavetable = &SIN_TABLE[0]; + } + } + } + return; + case 0x02: /* Timer 1 */ + OPL->T[0] = (256-v)*4; + break; + case 0x03: /* Timer 2 */ + OPL->T[1] = (256-v)*16; + return; + case 0x04: /* IRQ clear / mask and Timer enable */ + if(v&0x80) + { /* IRQ flag clear */ + OPL_STATUS_RESET(OPL,0x7f); + } + else + { /* set IRQ mask ,timer enable*/ + UINT8 st1 = v&1; + UINT8 st2 = (v>>1)&1; + /* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */ + OPL_STATUS_RESET(OPL,v&0x78); + OPL_STATUSMASK_SET(OPL,((~v)&0x78)|0x01); + /* timer 2 */ + if(OPL->st[1] != st2) + { + double interval = st2 ? (double)OPL->T[1]*OPL->TimerBase : 0.0; + OPL->st[1] = st2; + if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+1,interval); + } + /* timer 1 */ + if(OPL->st[0] != st1) + { + double interval = st1 ? (double)OPL->T[0]*OPL->TimerBase : 0.0; + OPL->st[0] = st1; + if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+0,interval); + } + } + return; #if BUILD_Y8950 - case 0x06: /* Key Board OUT */ - if(OPL->type&OPL_TYPE_KEYBOARD) - { - if(OPL->keyboardhandler_w) - OPL->keyboardhandler_w(OPL->keyboard_param,v); - else - LOG(LOG_WAR,("OPL:write unmapped KEYBOARD port\n")); - } - return; - case 0x07: /* DELTA-T controll : START,REC,MEMDATA,REPT,SPOFF,x,x,RST */ - if(OPL->type&OPL_TYPE_ADPCM) - YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v); - return; - case 0x08: /* MODE,DELTA-T : CSM,NOTESEL,x,x,smpl,da/ad,64k,rom */ - OPL->mode = v; - v&=0x1f; /* for DELTA-T unit */ - case 0x09: /* START ADD */ - case 0x0a: - case 0x0b: /* STOP ADD */ - case 0x0c: - case 0x0d: /* PRESCALE */ - case 0x0e: - case 0x0f: /* ADPCM data */ - case 0x10: /* DELTA-N */ - case 0x11: /* DELTA-N */ - case 0x12: /* EG-CTRL */ - if(OPL->type&OPL_TYPE_ADPCM) - YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v); - return; + case 0x06: /* Key Board OUT */ + if(OPL->type&OPL_TYPE_KEYBOARD) + { + if(OPL->keyboardhandler_w) + OPL->keyboardhandler_w(OPL->keyboard_param,v); + else + LOG(LOG_WAR,("OPL:write unmapped KEYBOARD port\n")); + } + return; + case 0x07: /* DELTA-T controll : START,REC,MEMDATA,REPT,SPOFF,x,x,RST */ + if(OPL->type&OPL_TYPE_ADPCM) + YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v); + return; + case 0x08: /* MODE,DELTA-T : CSM,NOTESEL,x,x,smpl,da/ad,64k,rom */ + OPL->mode = v; + v&=0x1f; /* for DELTA-T unit */ + case 0x09: /* START ADD */ + case 0x0a: + case 0x0b: /* STOP ADD */ + case 0x0c: + case 0x0d: /* PRESCALE */ + case 0x0e: + case 0x0f: /* ADPCM data */ + case 0x10: /* DELTA-N */ + case 0x11: /* DELTA-N */ + case 0x12: /* EG-CTRL */ + if(OPL->type&OPL_TYPE_ADPCM) + YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v); + return; #if 0 - case 0x15: /* DAC data */ - case 0x16: - case 0x17: /* SHIFT */ - return; - case 0x18: /* I/O CTRL (Direction) */ - if(OPL->type&OPL_TYPE_IO) - OPL->portDirection = v&0x0f; - return; - case 0x19: /* I/O DATA */ - if(OPL->type&OPL_TYPE_IO) - { - OPL->portLatch = v; - if(OPL->porthandler_w) - OPL->porthandler_w(OPL->port_param,v&OPL->portDirection); - } - return; - case 0x1a: /* PCM data */ - return; + case 0x15: /* DAC data */ + case 0x16: + case 0x17: /* SHIFT */ + return; + case 0x18: /* I/O CTRL (Direction) */ + if(OPL->type&OPL_TYPE_IO) + OPL->portDirection = v&0x0f; + return; + case 0x19: /* I/O DATA */ + if(OPL->type&OPL_TYPE_IO) + { + OPL->portLatch = v; + if(OPL->porthandler_w) + OPL->porthandler_w(OPL->port_param,v&OPL->portDirection); + } + return; + case 0x1a: /* PCM data */ + return; #endif #endif - } - break; - case 0x20: /* am,vib,ksr,eg type,mul */ - slot = slot_array[r&0x1f]; - if(slot == -1) return; - set_mul(OPL,slot,v); - return; - case 0x40: - slot = slot_array[r&0x1f]; - if(slot == -1) return; - set_ksl_tl(OPL,slot,v); - return; - case 0x60: - slot = slot_array[r&0x1f]; - if(slot == -1) return; - set_ar_dr(OPL,slot,v); - return; - case 0x80: - slot = slot_array[r&0x1f]; - if(slot == -1) return; - set_sl_rr(OPL,slot,v); - return; - case 0xa0: - switch(r) - { - case 0xbd: - /* amsep,vibdep,r,bd,sd,tom,tc,hh */ - { - UINT8 rkey = OPL->rythm^v; - OPL->ams_table = &AMS_TABLE[v&0x80 ? AMS_ENT : 0]; - OPL->vib_table = &VIB_TABLE[v&0x40 ? VIB_ENT : 0]; - OPL->rythm = v&0x3f; - if(OPL->rythm&0x20) - { + } + break; + case 0x20: /* am,vib,ksr,eg type,mul */ + slot = slot_array[r&0x1f]; + if(slot == -1) return; + set_mul(OPL,slot,v); + return; + case 0x40: + slot = slot_array[r&0x1f]; + if(slot == -1) return; + set_ksl_tl(OPL,slot,v); + return; + case 0x60: + slot = slot_array[r&0x1f]; + if(slot == -1) return; + set_ar_dr(OPL,slot,v); + return; + case 0x80: + slot = slot_array[r&0x1f]; + if(slot == -1) return; + set_sl_rr(OPL,slot,v); + return; + case 0xa0: + switch(r) + { + case 0xbd: + /* amsep,vibdep,r,bd,sd,tom,tc,hh */ + { + UINT8 rkey = OPL->rythm^v; + OPL->ams_table = &AMS_TABLE[v&0x80 ? AMS_ENT : 0]; + OPL->vib_table = &VIB_TABLE[v&0x40 ? VIB_ENT : 0]; + OPL->rythm = v&0x3f; + if(OPL->rythm&0x20) + { #if 0 - usrintf_showmessage("OPL Rythm mode select"); + usrintf_showmessage("OPL Rythm mode select"); #endif - /* BD key on/off */ - if(rkey&0x10) - { - if(v&0x10) - { - OPL->P_CH[6].op1_out[0] = OPL->P_CH[6].op1_out[1] = 0; - OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT1]); - OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT2]); - } - else - { - OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1]); - OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2]); - } - } - /* SD key on/off */ - if(rkey&0x08) - { - if(v&0x08) OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT2]); - else OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2]); - }/* TAM key on/off */ - if(rkey&0x04) - { - if(v&0x04) OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT1]); - else OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1]); - } - /* TOP-CY key on/off */ - if(rkey&0x02) - { - if(v&0x02) OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT2]); - else OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2]); - } - /* HH key on/off */ - if(rkey&0x01) - { - if(v&0x01) OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT1]); - else OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1]); - } - } - } - return; - } - /* keyon,block,fnum */ - if( (r&0x0f) > 8) return; - CH = &OPL->P_CH[r&0x0f]; - if(!(r&0x10)) - { /* a0-a8 */ - block_fnum = (CH->block_fnum&0x1f00) | v; - } - else - { /* b0-b8 */ - int keyon = (v>>5)&1; - block_fnum = ((v&0x1f)<<8) | (CH->block_fnum&0xff); - if(CH->keyon != keyon) - { - if( (CH->keyon=keyon) ) - { - CH->op1_out[0] = CH->op1_out[1] = 0; - OPL_KEYON(&CH->SLOT[SLOT1]); - OPL_KEYON(&CH->SLOT[SLOT2]); - } - else - { - OPL_KEYOFF(&CH->SLOT[SLOT1]); - OPL_KEYOFF(&CH->SLOT[SLOT2]); - } - } - } - /* update */ - if(CH->block_fnum != block_fnum) - { - int blockRv = 7-(block_fnum>>10); - int fnum = block_fnum&0x3ff; - CH->block_fnum = block_fnum; - - CH->ksl_base = KSL_TABLE[block_fnum>>6]; - CH->fc = OPL->FN_TABLE[fnum]>>blockRv; - CH->kcode = CH->block_fnum>>9; - if( (OPL->mode&0x40) && CH->block_fnum&0x100) CH->kcode |=1; - CALC_FCSLOT(CH,&CH->SLOT[SLOT1]); - CALC_FCSLOT(CH,&CH->SLOT[SLOT2]); - } - return; - case 0xc0: - /* FB,C */ - if( (r&0x0f) > 8) return; - CH = &OPL->P_CH[r&0x0f]; - { - int feedback = (v>>1)&7; - CH->FB = feedback ? (8+1) - feedback : 0; - CH->CON = v&1; - set_algorythm(CH); - } - return; - case 0xe0: /* wave type */ - slot = slot_array[r&0x1f]; - if(slot == -1) return; - CH = &OPL->P_CH[slot/2]; - if(OPL->wavesel) - { - /* LOG(LOG_INF,("OPL SLOT %d wave select %d\n",slot,v&3)); */ - CH->SLOT[slot&1].wavetable = &SIN_TABLE[(v&0x03)*SIN_ENT]; - } - return; - } + /* BD key on/off */ + if(rkey&0x10) + { + if(v&0x10) + { + OPL->P_CH[6].op1_out[0] = OPL->P_CH[6].op1_out[1] = 0; + OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT1]); + OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT2]); + } + else + { + OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1]); + OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2]); + } + } + /* SD key on/off */ + if(rkey&0x08) + { + if(v&0x08) OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT2]); + else OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2]); + }/* TAM key on/off */ + if(rkey&0x04) + { + if(v&0x04) OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT1]); + else OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1]); + } + /* TOP-CY key on/off */ + if(rkey&0x02) + { + if(v&0x02) OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT2]); + else OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2]); + } + /* HH key on/off */ + if(rkey&0x01) + { + if(v&0x01) OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT1]); + else OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1]); + } + } + } + return; + } + /* keyon,block,fnum */ + if( (r&0x0f) > 8) return; + CH = &OPL->P_CH[r&0x0f]; + if(!(r&0x10)) + { /* a0-a8 */ + block_fnum = (CH->block_fnum&0x1f00) | v; + } + else + { /* b0-b8 */ + int keyon = (v>>5)&1; + block_fnum = ((v&0x1f)<<8) | (CH->block_fnum&0xff); + if(CH->keyon != keyon) + { + if( (CH->keyon=keyon) ) + { + CH->op1_out[0] = CH->op1_out[1] = 0; + OPL_KEYON(&CH->SLOT[SLOT1]); + OPL_KEYON(&CH->SLOT[SLOT2]); + } + else + { + OPL_KEYOFF(&CH->SLOT[SLOT1]); + OPL_KEYOFF(&CH->SLOT[SLOT2]); + } + } + } + /* update */ + if(CH->block_fnum != block_fnum) + { + int blockRv = 7-(block_fnum>>10); + int fnum = block_fnum&0x3ff; + CH->block_fnum = block_fnum; + + CH->ksl_base = KSL_TABLE[block_fnum>>6]; + CH->fc = OPL->FN_TABLE[fnum]>>blockRv; + CH->kcode = CH->block_fnum>>9; + if( (OPL->mode&0x40) && CH->block_fnum&0x100) CH->kcode |=1; + CALC_FCSLOT(CH,&CH->SLOT[SLOT1]); + CALC_FCSLOT(CH,&CH->SLOT[SLOT2]); + } + return; + case 0xc0: + /* FB,C */ + if( (r&0x0f) > 8) return; + CH = &OPL->P_CH[r&0x0f]; + { + int feedback = (v>>1)&7; + CH->FB = feedback ? (8+1) - feedback : 0; + CH->CON = v&1; + set_algorythm(CH); + } + return; + case 0xe0: /* wave type */ + slot = slot_array[r&0x1f]; + if(slot == -1) return; + CH = &OPL->P_CH[slot/2]; + if(OPL->wavesel) + { + /* LOG(LOG_INF,("OPL SLOT %d wave select %d\n",slot,v&3)); */ + CH->SLOT[slot&1].wavetable = &SIN_TABLE[(v&0x03)*SIN_ENT]; + } + return; + } } /* lock/unlock for common table */ -static int OPL_LockTable(void) +static int OPL_LockTable() { - num_lock++; - if(num_lock>1) return 0; - /* first time */ - cur_chip = nullptr; - /* allocate total level table (128kb space) */ - if( !OPLOpenTable() ) - { - num_lock--; - return -1; - } - return 0; + num_lock++; + if(num_lock>1) return 0; + /* first time */ + cur_chip = NULL; + /* allocate total level table (128kb space) */ + if( !OPLOpenTable() ) + { + num_lock--; + return -1; + } + return 0; } -static void OPL_UnLockTable(void) +static void OPL_UnLockTable() { - if(num_lock) num_lock--; - if(num_lock) return; - /* last time */ - cur_chip = nullptr; - OPLCloseTable(); + if(num_lock) num_lock--; + if(num_lock) return; + /* last time */ + cur_chip = NULL; + OPLCloseTable(); } #if (BUILD_YM3812 || BUILD_YM3526) /*******************************************************************************/ -/* YM3812 local section */ +/* YM3812 local section */ /*******************************************************************************/ /* ---------- update one of chip ----------- */ void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length) { int i; - int data; - OPLSAMPLE *buf = buffer; - UINT32 amsCnt = OPL->amsCnt; - UINT32 vibCnt = OPL->vibCnt; - UINT8 rythm = OPL->rythm&0x20; - OPL_CH *CH,*R_CH; - - if( (void *)OPL != cur_chip ){ - cur_chip = (void *)OPL; - /* channel pointers */ - S_CH = OPL->P_CH; - E_CH = &S_CH[9]; - /* rythm slot */ - SLOT7_1 = &S_CH[7].SLOT[SLOT1]; - SLOT7_2 = &S_CH[7].SLOT[SLOT2]; - SLOT8_1 = &S_CH[8].SLOT[SLOT1]; - SLOT8_2 = &S_CH[8].SLOT[SLOT2]; - /* LFO state */ - amsIncr = OPL->amsIncr; - vibIncr = OPL->vibIncr; - ams_table = OPL->ams_table; - vib_table = OPL->vib_table; - } - R_CH = rythm ? &S_CH[6] : E_CH; + int data; + OPLSAMPLE *buf = buffer; + UINT32 amsCnt = OPL->amsCnt; + UINT32 vibCnt = OPL->vibCnt; + UINT8 rythm = OPL->rythm&0x20; + OPL_CH *CH,*R_CH; + + if( (void *)OPL != cur_chip ){ + cur_chip = (void *)OPL; + /* channel pointers */ + S_CH = OPL->P_CH; + E_CH = &S_CH[9]; + /* rythm slot */ + SLOT7_1 = &S_CH[7].SLOT[SLOT1]; + SLOT7_2 = &S_CH[7].SLOT[SLOT2]; + SLOT8_1 = &S_CH[8].SLOT[SLOT1]; + SLOT8_2 = &S_CH[8].SLOT[SLOT2]; + /* LFO state */ + amsIncr = OPL->amsIncr; + vibIncr = OPL->vibIncr; + ams_table = OPL->ams_table; + vib_table = OPL->vib_table; + } + R_CH = rythm ? &S_CH[6] : E_CH; for( i=0; i < length ; i++ ) - { - /* channel A channel B channel C */ - /* LFO */ - ams = ams_table[(amsCnt+=amsIncr)>>AMS_SHIFT]; - vib = vib_table[(vibCnt+=vibIncr)>>VIB_SHIFT]; - outd[0] = 0; - /* FM part */ - for(CH=S_CH ; CH < R_CH ; CH++) - OPL_CALC_CH(CH); - /* Rythn part */ - if(rythm) - OPL_CALC_RH(S_CH); - /* limit check */ - data = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT ); - /* store to sound buffer */ - buf[i] = data >> OPL_OUTSB; - } - - OPL->amsCnt = amsCnt; - OPL->vibCnt = vibCnt; + { + /* channel A channel B channel C */ + /* LFO */ + ams = ams_table[(amsCnt+=amsIncr)>>AMS_SHIFT]; + vib = vib_table[(vibCnt+=vibIncr)>>VIB_SHIFT]; + outd[0] = 0; + /* FM part */ + for(CH=S_CH ; CH < R_CH ; CH++) + OPL_CALC_CH(CH); + /* Rythn part */ + if(rythm) + OPL_CALC_RH(S_CH); + /* limit check */ + data = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT ); + /* store to sound buffer */ + buf[i] = data >> OPL_OUTSB; + } + + OPL->amsCnt = amsCnt; + OPL->vibCnt = vibCnt; #ifdef OPL_OUTPUT_LOG - if(opl_dbg_fp) - { - for(opl_dbg_chip=0;opl_dbg_chip<opl_dbg_maxchip;opl_dbg_chip++) - if( opl_dbg_opl[opl_dbg_chip] == OPL) break; - fprintf(opl_dbg_fp,"%c%c%c",0x20+opl_dbg_chip,length&0xff,length/256); - } + if(opl_dbg_fp) + { + for(opl_dbg_chip=0;opl_dbg_chip<opl_dbg_maxchip;opl_dbg_chip++) + if( opl_dbg_opl[opl_dbg_chip] == OPL) break; + fprintf(opl_dbg_fp,"%c%c%c",0x20+opl_dbg_chip,length&0xff,length/256); + } #endif } #endif /* (BUILD_YM3812 || BUILD_YM3526) */ @@ -1106,104 +1105,104 @@ void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length) void Y8950UpdateOne(FM_OPL *OPL, INT16 *buffer, int length) { int i; - int data; - OPLSAMPLE *buf = buffer; - UINT32 amsCnt = OPL->amsCnt; - UINT32 vibCnt = OPL->vibCnt; - UINT8 rythm = OPL->rythm&0x20; - OPL_CH *CH,*R_CH; - YM_DELTAT *DELTAT = OPL->deltat; - - /* setup DELTA-T unit */ - YM_DELTAT_DECODE_PRESET(DELTAT); - - if( (void *)OPL != cur_chip ){ - cur_chip = (void *)OPL; - /* channel pointers */ - S_CH = OPL->P_CH; - E_CH = &S_CH[9]; - /* rythm slot */ - SLOT7_1 = &S_CH[7].SLOT[SLOT1]; - SLOT7_2 = &S_CH[7].SLOT[SLOT2]; - SLOT8_1 = &S_CH[8].SLOT[SLOT1]; - SLOT8_2 = &S_CH[8].SLOT[SLOT2]; - /* LFO state */ - amsIncr = OPL->amsIncr; - vibIncr = OPL->vibIncr; - ams_table = OPL->ams_table; - vib_table = OPL->vib_table; - } - R_CH = rythm ? &S_CH[6] : E_CH; + int data; + OPLSAMPLE *buf = buffer; + UINT32 amsCnt = OPL->amsCnt; + UINT32 vibCnt = OPL->vibCnt; + UINT8 rythm = OPL->rythm&0x20; + OPL_CH *CH,*R_CH; + YM_DELTAT *DELTAT = OPL->deltat; + + /* setup DELTA-T unit */ + YM_DELTAT_DECODE_PRESET(DELTAT); + + if( (void *)OPL != cur_chip ){ + cur_chip = (void *)OPL; + /* channel pointers */ + S_CH = OPL->P_CH; + E_CH = &S_CH[9]; + /* rythm slot */ + SLOT7_1 = &S_CH[7].SLOT[SLOT1]; + SLOT7_2 = &S_CH[7].SLOT[SLOT2]; + SLOT8_1 = &S_CH[8].SLOT[SLOT1]; + SLOT8_2 = &S_CH[8].SLOT[SLOT2]; + /* LFO state */ + amsIncr = OPL->amsIncr; + vibIncr = OPL->vibIncr; + ams_table = OPL->ams_table; + vib_table = OPL->vib_table; + } + R_CH = rythm ? &S_CH[6] : E_CH; for( i=0; i < length ; i++ ) - { - /* channel A channel B channel C */ - /* LFO */ - ams = ams_table[(amsCnt+=amsIncr)>>AMS_SHIFT]; - vib = vib_table[(vibCnt+=vibIncr)>>VIB_SHIFT]; - outd[0] = 0; - /* deltaT ADPCM */ - if( DELTAT->portstate ) - YM_DELTAT_ADPCM_CALC(DELTAT); - /* FM part */ - for(CH=S_CH ; CH < R_CH ; CH++) - OPL_CALC_CH(CH); - /* Rythn part */ - if(rythm) - OPL_CALC_RH(S_CH); - /* limit check */ - data = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT ); - /* store to sound buffer */ - buf[i] = data >> OPL_OUTSB; - } - OPL->amsCnt = amsCnt; - OPL->vibCnt = vibCnt; - /* deltaT START flag */ - if( !DELTAT->portstate ) - OPL->status &= 0xfe; + { + /* channel A channel B channel C */ + /* LFO */ + ams = ams_table[(amsCnt+=amsIncr)>>AMS_SHIFT]; + vib = vib_table[(vibCnt+=vibIncr)>>VIB_SHIFT]; + outd[0] = 0; + /* deltaT ADPCM */ + if( DELTAT->portstate ) + YM_DELTAT_ADPCM_CALC(DELTAT); + /* FM part */ + for(CH=S_CH ; CH < R_CH ; CH++) + OPL_CALC_CH(CH); + /* Rythn part */ + if(rythm) + OPL_CALC_RH(S_CH); + /* limit check */ + data = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT ); + /* store to sound buffer */ + buf[i] = data >> OPL_OUTSB; + } + OPL->amsCnt = amsCnt; + OPL->vibCnt = vibCnt; + /* deltaT START flag */ + if( !DELTAT->portstate ) + OPL->status &= 0xfe; } #endif /* ---------- reset one of chip ---------- */ void OPLResetChip(FM_OPL *OPL) { - int c,s; - int i; - - /* reset chip */ - OPL->mode = 0; /* normal mode */ - OPL_STATUS_RESET(OPL,0x7f); - /* reset with register write */ - OPLWriteReg(OPL,0x01,0); /* wabesel disable */ - OPLWriteReg(OPL,0x02,0); /* Timer1 */ - OPLWriteReg(OPL,0x03,0); /* Timer2 */ - OPLWriteReg(OPL,0x04,0); /* IRQ mask clear */ - for(i = 0xff ; i >= 0x20 ; i-- ) OPLWriteReg(OPL,i,0); - /* reset OPerator paramater */ - for( c = 0 ; c < OPL->max_ch ; c++ ) - { - OPL_CH *CH = &OPL->P_CH[c]; - /* OPL->P_CH[c].PAN = OPN_CENTER; */ - for(s = 0 ; s < 2 ; s++ ) - { - /* wave table */ - CH->SLOT[s].wavetable = &SIN_TABLE[0]; - /* CH->SLOT[s].evm = ENV_MOD_RR; */ - CH->SLOT[s].evc = EG_OFF; - CH->SLOT[s].eve = EG_OFF+1; - CH->SLOT[s].evs = 0; - } - } + int c,s; + int i; + + /* reset chip */ + OPL->mode = 0; /* normal mode */ + OPL_STATUS_RESET(OPL,0x7f); + /* reset with register write */ + OPLWriteReg(OPL,0x01,0); /* wabesel disable */ + OPLWriteReg(OPL,0x02,0); /* Timer1 */ + OPLWriteReg(OPL,0x03,0); /* Timer2 */ + OPLWriteReg(OPL,0x04,0); /* IRQ mask clear */ + for(i = 0xff ; i >= 0x20 ; i-- ) OPLWriteReg(OPL,i,0); + /* reset OPerator paramater */ + for( c = 0 ; c < OPL->max_ch ; c++ ) + { + OPL_CH *CH = &OPL->P_CH[c]; + /* OPL->P_CH[c].PAN = OPN_CENTER; */ + for(s = 0 ; s < 2 ; s++ ) + { + /* wave table */ + CH->SLOT[s].wavetable = &SIN_TABLE[0]; + /* CH->SLOT[s].evm = ENV_MOD_RR; */ + CH->SLOT[s].evc = EG_OFF; + CH->SLOT[s].eve = EG_OFF+1; + CH->SLOT[s].evs = 0; + } + } #if BUILD_Y8950 - if(OPL->type&OPL_TYPE_ADPCM) - { - YM_DELTAT *DELTAT = OPL->deltat; - - DELTAT->freqbase = OPL->freqbase; - DELTAT->output_pointer = outd; - DELTAT->portshift = 5; - DELTAT->output_range = DELTAT_MIXING_LEVEL<<TL_BITS; - YM_DELTAT_ADPCM_Reset(DELTAT,0); - } + if(OPL->type&OPL_TYPE_ADPCM) + { + YM_DELTAT *DELTAT = OPL->deltat; + + DELTAT->freqbase = OPL->freqbase; + DELTAT->output_pointer = outd; + DELTAT->portshift = 5; + DELTAT->output_range = DELTAT_MIXING_LEVEL<<TL_BITS; + YM_DELTAT_ADPCM_Reset(DELTAT,0); + } #endif } @@ -1211,183 +1210,183 @@ void OPLResetChip(FM_OPL *OPL) /* 'rate' is sampling rate and 'bufsiz' is the size of the */ FM_OPL *OPLCreate(int type, int clock, int rate) { - char *ptr; - FM_OPL *OPL; - int state_size; - int max_ch = 9; /* normaly 9 channels */ - - if( OPL_LockTable() ==-1) return nullptr; - /* allocate OPL state space */ - state_size = sizeof(FM_OPL); - state_size += sizeof(OPL_CH)*max_ch; + char *ptr; + FM_OPL *OPL; + int state_size; + int max_ch = 9; /* normaly 9 channels */ + + if( OPL_LockTable() ==-1) return NULL; + /* allocate OPL state space */ + state_size = sizeof(FM_OPL); + state_size += sizeof(OPL_CH)*max_ch; #if BUILD_Y8950 - if(type&OPL_TYPE_ADPCM) state_size+= sizeof(YM_DELTAT); + if(type&OPL_TYPE_ADPCM) state_size+= sizeof(YM_DELTAT); #endif - /* allocate memory block */ - ptr = (char*)malloc(state_size); - if(ptr==nullptr) return nullptr; - /* clear */ - memset(ptr,0,state_size); - OPL = (FM_OPL *)ptr; ptr+=sizeof(FM_OPL); - OPL->P_CH = (OPL_CH *)ptr; ptr+=sizeof(OPL_CH)*max_ch; + /* allocate memory block */ + ptr = (char*)malloc(state_size); + if(ptr==NULL) return NULL; + /* clear */ + memset(ptr,0,state_size); + OPL = (FM_OPL *)ptr; ptr+=sizeof(FM_OPL); + OPL->P_CH = (OPL_CH *)ptr; ptr+=sizeof(OPL_CH)*max_ch; #if BUILD_Y8950 - if(type&OPL_TYPE_ADPCM) OPL->deltat = (YM_DELTAT *)ptr; ptr+=sizeof(YM_DELTAT); + if(type&OPL_TYPE_ADPCM) OPL->deltat = (YM_DELTAT *)ptr; ptr+=sizeof(YM_DELTAT); #endif - /* set channel state pointer */ - OPL->type = type; - OPL->clock = clock; - OPL->rate = rate; - OPL->max_ch = max_ch; - /* init grobal tables */ - OPL_initalize(OPL); - /* reset chip */ - OPLResetChip(OPL); + /* set channel state pointer */ + OPL->type = type; + OPL->clock = clock; + OPL->rate = rate; + OPL->max_ch = max_ch; + /* init grobal tables */ + OPL_initalize(OPL); + /* reset chip */ + OPLResetChip(OPL); #ifdef OPL_OUTPUT_LOG - if(!opl_dbg_fp) - { - opl_dbg_fp = fopen("opllog.opl","wb"); - opl_dbg_maxchip = 0; - } - if(opl_dbg_fp) - { - opl_dbg_opl[opl_dbg_maxchip] = OPL; - fprintf(opl_dbg_fp,"%c%c%c%c%c%c",0x00+opl_dbg_maxchip, - type, - clock&0xff, - (clock/0x100)&0xff, - (clock/0x10000)&0xff, - (clock/0x1000000)&0xff); - opl_dbg_maxchip++; - } + if(!opl_dbg_fp) + { + opl_dbg_fp = fopen("opllog.opl","wb"); + opl_dbg_maxchip = 0; + } + if(opl_dbg_fp) + { + opl_dbg_opl[opl_dbg_maxchip] = OPL; + fprintf(opl_dbg_fp,"%c%c%c%c%c%c",0x00+opl_dbg_maxchip, + type, + clock&0xff, + (clock/0x100)&0xff, + (clock/0x10000)&0xff, + (clock/0x1000000)&0xff); + opl_dbg_maxchip++; + } #endif - return OPL; + return OPL; } /* ---------- Destroy one of vietual YM3812 ---------- */ void OPLDestroy(FM_OPL *OPL) { #ifdef OPL_OUTPUT_LOG - if(opl_dbg_fp) - { - fclose(opl_dbg_fp); - opl_dbg_fp = nullptr; - } + if(opl_dbg_fp) + { + fclose(opl_dbg_fp); + opl_dbg_fp = NULL; + } #endif - OPL_UnLockTable(); - free(OPL); + OPL_UnLockTable(); + free(OPL); } /* ---------- Option handlers ---------- */ void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset) { - OPL->TimerHandler = TimerHandler; - OPL->TimerParam = channelOffset; + OPL->TimerHandler = TimerHandler; + OPL->TimerParam = channelOffset; } void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param) { - OPL->IRQHandler = IRQHandler; - OPL->IRQParam = param; + OPL->IRQHandler = IRQHandler; + OPL->IRQParam = param; } void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int param) { - OPL->UpdateHandler = UpdateHandler; - OPL->UpdateParam = param; + OPL->UpdateHandler = UpdateHandler; + OPL->UpdateParam = param; } #if BUILD_Y8950 void OPLSetPortHandler(FM_OPL *OPL,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,int param) { - OPL->porthandler_w = PortHandler_w; - OPL->porthandler_r = PortHandler_r; - OPL->port_param = param; + OPL->porthandler_w = PortHandler_w; + OPL->porthandler_r = PortHandler_r; + OPL->port_param = param; } void OPLSetKeyboardHandler(FM_OPL *OPL,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,int param) { - OPL->keyboardhandler_w = KeyboardHandler_w; - OPL->keyboardhandler_r = KeyboardHandler_r; - OPL->keyboard_param = param; + OPL->keyboardhandler_w = KeyboardHandler_w; + OPL->keyboardhandler_r = KeyboardHandler_r; + OPL->keyboard_param = param; } #endif /* ---------- YM3812 I/O interface ---------- */ int OPLWrite(FM_OPL *OPL,int a,int v) { - if( !(a&1) ) - { /* address port */ - OPL->address = v & 0xff; - } - else - { /* data port */ - if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0); + if( !(a&1) ) + { /* address port */ + OPL->address = v & 0xff; + } + else + { /* data port */ + if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0); #ifdef OPL_OUTPUT_LOG - if(opl_dbg_fp) - { - for(opl_dbg_chip=0;opl_dbg_chip<opl_dbg_maxchip;opl_dbg_chip++) - if( opl_dbg_opl[opl_dbg_chip] == OPL) break; - fprintf(opl_dbg_fp,"%c%c%c",0x10+opl_dbg_chip,OPL->address,v); - } + if(opl_dbg_fp) + { + for(opl_dbg_chip=0;opl_dbg_chip<opl_dbg_maxchip;opl_dbg_chip++) + if( opl_dbg_opl[opl_dbg_chip] == OPL) break; + fprintf(opl_dbg_fp,"%c%c%c",0x10+opl_dbg_chip,OPL->address,v); + } #endif - OPLWriteReg(OPL,OPL->address,v); - } - return OPL->status>>7; + OPLWriteReg(OPL,OPL->address,v); + } + return OPL->status>>7; } unsigned char OPLRead(FM_OPL *OPL,int a) { - if( !(a&1) ) - { /* status port */ - return OPL->status & (OPL->statusmask|0x80); - } - /* data port */ - switch(OPL->address) - { - case 0x05: /* KeyBoard IN */ - if(OPL->type&OPL_TYPE_KEYBOARD) - { - if(OPL->keyboardhandler_r) - return OPL->keyboardhandler_r(OPL->keyboard_param); - else - LOG(LOG_WAR,("OPL:read unmapped KEYBOARD port\n")); - } - return 0; + if( !(a&1) ) + { /* status port */ + return OPL->status & (OPL->statusmask|0x80); + } + /* data port */ + switch(OPL->address) + { + case 0x05: /* KeyBoard IN */ + if(OPL->type&OPL_TYPE_KEYBOARD) + { + if(OPL->keyboardhandler_r) + return OPL->keyboardhandler_r(OPL->keyboard_param); + else + LOG(LOG_WAR,("OPL:read unmapped KEYBOARD port\n")); + } + return 0; #if 0 - case 0x0f: /* ADPCM-DATA */ - return 0; + case 0x0f: /* ADPCM-DATA */ + return 0; #endif - case 0x19: /* I/O DATA */ - if(OPL->type&OPL_TYPE_IO) - { - if(OPL->porthandler_r) - return OPL->porthandler_r(OPL->port_param); - else - LOG(LOG_WAR,("OPL:read unmapped I/O port\n")); - } - return 0; - case 0x1a: /* PCM-DATA */ - return 0; - } - return 0; + case 0x19: /* I/O DATA */ + if(OPL->type&OPL_TYPE_IO) + { + if(OPL->porthandler_r) + return OPL->porthandler_r(OPL->port_param); + else + LOG(LOG_WAR,("OPL:read unmapped I/O port\n")); + } + return 0; + case 0x1a: /* PCM-DATA */ + return 0; + } + return 0; } int OPLTimerOver(FM_OPL *OPL,int c) { - if( c ) - { /* Timer B */ - OPL_STATUS_SET(OPL,0x20); - } - else - { /* Timer A */ - OPL_STATUS_SET(OPL,0x40); - /* CSM mode key,TL controll */ - if( OPL->mode & 0x80 ) - { /* CSM mode total level latch and auto key on */ - int ch; - if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0); - for(ch=0;ch<9;ch++) - CSMKeyControll( &OPL->P_CH[ch] ); - } - } - /* reload timer */ - if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+c,(double)OPL->T[c]*OPL->TimerBase); - return OPL->status>>7; + if( c ) + { /* Timer B */ + OPL_STATUS_SET(OPL,0x20); + } + else + { /* Timer A */ + OPL_STATUS_SET(OPL,0x40); + /* CSM mode key,TL controll */ + if( OPL->mode & 0x80 ) + { /* CSM mode total level latch and auto key on */ + int ch; + if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0); + for(ch=0;ch<9;ch++) + CSMKeyControll( &OPL->P_CH[ch] ); + } + } + /* reload timer */ + if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+c,(double)OPL->T[c]*OPL->TimerBase); + return OPL->status>>7; } diff --git a/src/adplug/core/fmopl.h b/src/adplug/core/fmopl.h index a01ff90..cfa0e02 100644 --- a/src/adplug/core/fmopl.h +++ b/src/adplug/core/fmopl.h @@ -13,12 +13,12 @@ /* compiler dependence */ #ifndef OSD_CPU_H #define OSD_CPU_H -typedef unsigned char UINT8; /* unsigned 8bit */ -typedef unsigned short UINT16; /* unsigned 16bit */ -typedef unsigned int UINT32; /* unsigned 32bit */ -typedef signed char INT8; /* signed 8bit */ -typedef signed short INT16; /* signed 16bit */ -typedef signed int INT32; /* signed 32bit */ +typedef unsigned char UINT8; /* unsigned 8bit */ +typedef unsigned short UINT16; /* unsigned 16bit */ +typedef unsigned int UINT32; /* unsigned 32bit */ +typedef signed char INT8; /* signed 8bit */ +typedef signed short INT16; /* signed 16bit */ +typedef signed int INT32; /* signed 32bit */ #endif #if (OPL_OUTPUT_BIT==16) @@ -49,102 +49,102 @@ typedef unsigned char (*OPL_PORTHANDLER_R)(int param); /* Saving is necessary for member of the 'R' mark for suspend/resume */ /* ---------- OPL one of slot ---------- */ typedef struct fm_opl_slot { - INT32 TL; /* total level :TL << 8 */ - INT32 TLL; /* adjusted now TL */ - UINT8 KSR; /* key scale rate :(shift down bit) */ - INT32 *AR; /* attack rate :&AR_TABLE[AR<<2] */ - INT32 *DR; /* decay rate :&DR_TALBE[DR<<2] */ - INT32 SL; /* sustin level :SL_TALBE[SL] */ - INT32 *RR; /* release rate :&DR_TABLE[RR<<2] */ - UINT8 ksl; /* keyscale level :(shift down bits) */ - UINT8 ksr; /* key scale rate :kcode>>KSR */ - UINT32 mul; /* multiple :ML_TABLE[ML] */ - UINT32 Cnt; /* frequency count : */ - UINT32 Incr; /* frequency step : */ - /* envelope generator state */ - UINT8 eg_typ; /* envelope type flag */ - UINT8 evm; /* envelope phase */ - INT32 evc; /* envelope counter */ - INT32 eve; /* envelope counter end point */ - INT32 evs; /* envelope counter step */ - INT32 evsa; /* envelope step for AR :AR[ksr] */ - INT32 evsd; /* envelope step for DR :DR[ksr] */ - INT32 evsr; /* envelope step for RR :RR[ksr] */ - /* LFO */ - UINT8 ams; /* ams flag */ - UINT8 vib; /* vibrate flag */ - /* wave selector */ - INT32 **wavetable; + INT32 TL; /* total level :TL << 8 */ + INT32 TLL; /* adjusted now TL */ + UINT8 KSR; /* key scale rate :(shift down bit) */ + INT32 *AR; /* attack rate :&AR_TABLE[AR<<2] */ + INT32 *DR; /* decay rate :&DR_TALBE[DR<<2] */ + INT32 SL; /* sustin level :SL_TALBE[SL] */ + INT32 *RR; /* release rate :&DR_TABLE[RR<<2] */ + UINT8 ksl; /* keyscale level :(shift down bits) */ + UINT8 ksr; /* key scale rate :kcode>>KSR */ + UINT32 mul; /* multiple :ML_TABLE[ML] */ + UINT32 Cnt; /* frequency count : */ + UINT32 Incr; /* frequency step : */ + /* envelope generator state */ + UINT8 eg_typ; /* envelope type flag */ + UINT8 evm; /* envelope phase */ + INT32 evc; /* envelope counter */ + INT32 eve; /* envelope counter end point */ + INT32 evs; /* envelope counter step */ + INT32 evsa; /* envelope step for AR :AR[ksr] */ + INT32 evsd; /* envelope step for DR :DR[ksr] */ + INT32 evsr; /* envelope step for RR :RR[ksr] */ + /* LFO */ + UINT8 ams; /* ams flag */ + UINT8 vib; /* vibrate flag */ + /* wave selector */ + INT32 **wavetable; }OPL_SLOT; /* ---------- OPL one of channel ---------- */ typedef struct fm_opl_channel { - OPL_SLOT SLOT[2]; - UINT8 CON; /* connection type */ - UINT8 FB; /* feed back :(shift down bit) */ - INT32 *connect1; /* slot1 output pointer */ - INT32 *connect2; /* slot2 output pointer */ - INT32 op1_out[2]; /* slot1 output for selfeedback */ - /* phase generator state */ - UINT32 block_fnum; /* block+fnum : */ - UINT8 kcode; /* key code : KeyScaleCode */ - UINT32 fc; /* Freq. Increment base */ - UINT32 ksl_base; /* KeyScaleLevel Base step */ - UINT8 keyon; /* key on/off flag */ + OPL_SLOT SLOT[2]; + UINT8 CON; /* connection type */ + UINT8 FB; /* feed back :(shift down bit) */ + INT32 *connect1; /* slot1 output pointer */ + INT32 *connect2; /* slot2 output pointer */ + INT32 op1_out[2]; /* slot1 output for selfeedback */ + /* phase generator state */ + UINT32 block_fnum; /* block+fnum : */ + UINT8 kcode; /* key code : KeyScaleCode */ + UINT32 fc; /* Freq. Increment base */ + UINT32 ksl_base; /* KeyScaleLevel Base step */ + UINT8 keyon; /* key on/off flag */ } OPL_CH; /* OPL state */ typedef struct fm_opl_f { - UINT8 type; /* chip type */ - int clock; /* master clock (Hz) */ - int rate; /* sampling rate (Hz) */ - double freqbase; /* frequency base */ - double TimerBase; /* Timer base time (==sampling time) */ - UINT8 address; /* address register */ - UINT8 status; /* status flag */ - UINT8 statusmask; /* status mask */ - UINT32 mode; /* Reg.08 : CSM , notesel,etc. */ - /* Timer */ - int T[2]; /* timer counter */ - UINT8 st[2]; /* timer enable */ - /* FM channel slots */ - OPL_CH *P_CH; /* pointer of CH */ - int max_ch; /* maximum channel */ - /* Rythm sention */ - UINT8 rythm; /* Rythm mode , key flag */ + UINT8 type; /* chip type */ + int clock; /* master clock (Hz) */ + int rate; /* sampling rate (Hz) */ + double freqbase; /* frequency base */ + double TimerBase; /* Timer base time (==sampling time) */ + UINT8 address; /* address register */ + UINT8 status; /* status flag */ + UINT8 statusmask; /* status mask */ + UINT32 mode; /* Reg.08 : CSM , notesel,etc. */ + /* Timer */ + int T[2]; /* timer counter */ + UINT8 st[2]; /* timer enable */ + /* FM channel slots */ + OPL_CH *P_CH; /* pointer of CH */ + int max_ch; /* maximum channel */ + /* Rythm sention */ + UINT8 rythm; /* Rythm mode , key flag */ #if BUILD_Y8950 - /* Delta-T ADPCM unit (Y8950) */ - YM_DELTAT *deltat; /* DELTA-T ADPCM */ + /* Delta-T ADPCM unit (Y8950) */ + YM_DELTAT *deltat; /* DELTA-T ADPCM */ #endif - /* Keyboard / I/O interface unit (Y8950) */ - UINT8 portDirection; - UINT8 portLatch; - OPL_PORTHANDLER_R porthandler_r; - OPL_PORTHANDLER_W porthandler_w; - int port_param; - OPL_PORTHANDLER_R keyboardhandler_r; - OPL_PORTHANDLER_W keyboardhandler_w; - int keyboard_param; - /* time tables */ - INT32 AR_TABLE[75]; /* atttack rate tables */ - INT32 DR_TABLE[75]; /* decay rate tables */ - UINT32 FN_TABLE[1024]; /* fnumber -> increment counter */ - /* LFO */ - INT32 *ams_table; - INT32 *vib_table; - INT32 amsCnt; - INT32 amsIncr; - INT32 vibCnt; - INT32 vibIncr; - /* wave selector enable flag */ - UINT8 wavesel; - /* external event callback handler */ - OPL_TIMERHANDLER TimerHandler; /* TIMER handler */ - int TimerParam; /* TIMER parameter */ - OPL_IRQHANDLER IRQHandler; /* IRQ handler */ - int IRQParam; /* IRQ parameter */ - OPL_UPDATEHANDLER UpdateHandler; /* stream update handler */ - int UpdateParam; /* stream update parameter */ + /* Keyboard / I/O interface unit (Y8950) */ + UINT8 portDirection; + UINT8 portLatch; + OPL_PORTHANDLER_R porthandler_r; + OPL_PORTHANDLER_W porthandler_w; + int port_param; + OPL_PORTHANDLER_R keyboardhandler_r; + OPL_PORTHANDLER_W keyboardhandler_w; + int keyboard_param; + /* time tables */ + INT32 AR_TABLE[75]; /* atttack rate tables */ + INT32 DR_TABLE[75]; /* decay rate tables */ + UINT32 FN_TABLE[1024]; /* fnumber -> increment counter */ + /* LFO */ + INT32 *ams_table; + INT32 *vib_table; + INT32 amsCnt; + INT32 amsIncr; + INT32 vibCnt; + INT32 vibIncr; + /* wave selector enable flag */ + UINT8 wavesel; + /* external event callback handler */ + OPL_TIMERHANDLER TimerHandler; /* TIMER handler */ + int TimerParam; /* TIMER parameter */ + OPL_IRQHANDLER IRQHandler; /* IRQ handler */ + int IRQParam; /* IRQ parameter */ + OPL_UPDATEHANDLER UpdateHandler; /* stream update handler */ + int UpdateParam; /* stream update parameter */ } FM_OPL; /* ---------- Generic interface section ---------- */ diff --git a/src/adplug/core/fprovide.cc b/src/adplug/core/fprovide.cc index 7b6c665..034b407 100644 --- a/src/adplug/core/fprovide.cc +++ b/src/adplug/core/fprovide.cc @@ -20,41 +20,40 @@ */ #include <string.h> -#include <binio.h> -#include <binfile.h> +#include "binio.h" +#include "binfile.h" #include "fprovide.h" - -#include <libaudcore/audstrings.h> +#include "binio_virtual.h" /***** CFileProvider *****/ bool CFileProvider::extension(const std::string &filename, - const std::string &extension) + const std::string &extension) { - return str_has_suffix_nocase(filename.c_str(), extension.c_str()); + const char *fname = filename.c_str(), *ext = extension.c_str(); + + if(strlen(fname) < strlen(ext) || + strcasecmp(fname + strlen(fname) - strlen(ext), ext)) + return false; + else + return true; } unsigned long CFileProvider::filesize(binistream *f) { - unsigned long oldpos = f->pos(), size; - - f->seek(0, binio::End); - size = f->pos(); - f->seek(oldpos, binio::Set); - - return size; + return static_cast<vfsistream*>(f)->size(); } -/***** CProvider_Filesystem *****/ - -binistream *CProvider_Filesystem::open(VFSFile &fd) const +binistream *CFileProvider::open(std::string filename) const { - if(!fd) return 0; + binistream *f; - vfsistream *f = new vfsistream(&fd); + if (!strcmp(filename.c_str(), m_file.filename()) && !m_file.fseek(0, VFS_SEEK_SET)) + f = new vfsistream(&m_file); + else + f = new vfsistream(filename); - if(!f) return 0; if(f->error()) { delete f; return 0; } // Open all files as little endian with IEEE floats by default @@ -62,12 +61,3 @@ binistream *CProvider_Filesystem::open(VFSFile &fd) const return f; } - -void CProvider_Filesystem::close(binistream *f) const -{ - vfsistream *ff = (vfsistream *)f; - - if(f) { - delete ff; - } -} diff --git a/src/adplug/core/fprovide.h b/src/adplug/core/fprovide.h index 6755ee9..adf8d35 100644 --- a/src/adplug/core/fprovide.h +++ b/src/adplug/core/fprovide.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2006 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -23,28 +23,27 @@ #define H_ADPLUG_FILEPROVIDER #include <string> -#include "binio_virtual.h" +#include "binio.h" + +class VFSFile; class CFileProvider { public: - virtual ~CFileProvider() - { - } + CFileProvider(VFSFile &file) : + m_file(file) {} - virtual binistream *open(VFSFile &) const = 0; - virtual void close(binistream *) const = 0; + binistream *open(std::string filename) const; + + static void close(binistream *f) + { delete f; } static bool extension(const std::string &filename, - const std::string &extension); + const std::string &extension); static unsigned long filesize(binistream *f); -}; -class CProvider_Filesystem: public CFileProvider -{ -public: - virtual binistream *open(VFSFile &) const; - virtual void close(binistream *f) const; +private: + VFSFile &m_file; }; #endif diff --git a/src/adplug/core/hsc.cc b/src/adplug/core/hsc.cc index 121d2d2..8430111 100644 --- a/src/adplug/core/hsc.cc +++ b/src/adplug/core/hsc.cc @@ -26,102 +26,84 @@ /*** public methods **************************************/ -CPlayer * -ChscPlayer::factory (Copl * newopl) +CPlayer *ChscPlayer::factory(Copl *newopl) { - return new ChscPlayer (newopl); + return new ChscPlayer(newopl); } -bool -ChscPlayer::load (VFSFile & fd, const CFileProvider & fp) +bool ChscPlayer::load(const std::string &filename, const CFileProvider &fp) { - binistream *f = fp.open (fd); - int i; + binistream *f = fp.open(filename); + int i; // file validation section - if (!f || !fp.extension (fd.filename (), ".hsc") || fp.filesize (f) > 59187) - { - AdPlug_LogWrite ("ChscPlayer::load(\"%s\"): Not a HSC file!\n", - fd.filename ()); - fp.close (f); + if(!f || !fp.extension(filename, ".hsc") || fp.filesize(f) > 59187) { + AdPlug_LogWrite("ChscPlayer::load(\"%s\"): Not a HSC file!\n", filename.c_str()); + fp.close(f); return false; } // load section - for (i = 0; i < 128 * 12; i++) // load instruments - *((unsigned char *) instr + i) = f->readInt (1); - for (i = 0; i < 128; i++) - { // correct instruments + for(i=0;i<128*12;i++) // load instruments + *((unsigned char *)instr + i) = f->readInt(1); + for (i=0;i<128;i++) { // correct instruments instr[i][2] ^= (instr[i][2] & 0x40) << 1; instr[i][3] ^= (instr[i][3] & 0x40) << 1; - instr[i][11] >>= 4; // slide + instr[i][11] >>= 4; // slide } - for (i = 0; i < 51; i++) - song[i] = f->readInt (1); // load tracklist - for (i = 0; i < 50 * 64 * 9; i++) // load patterns - *((char *) patterns + i) = f->readInt (1); + for(i=0;i<51;i++) song[i] = f->readInt(1); // load tracklist + for(i=0;i<50*64*9;i++) // load patterns + *((char *)patterns + i) = f->readInt(1); - fp.close (f); - rewind (0); // rewind module + fp.close(f); + rewind(0); // rewind module return true; } -bool -ChscPlayer::update () +bool ChscPlayer::update() { // general vars - unsigned char chan, pattnr, note, effect, eff_op, inst, vol, Okt, db; - unsigned short Fnr; - unsigned long pattoff; + unsigned char chan,pattnr,note,effect,eff_op,inst,vol,Okt,db; + unsigned short Fnr; + unsigned long pattoff; - del--; // player speed handling - if (del) + del--; // player speed handling + if(del) return !songend; // nothing done - if (fadein) // fade-in handling + if(fadein) // fade-in handling fadein--; pattnr = song[songpos]; - if (pattnr == 0xff) - { // arrangement handling - songend = 1; // set end-flag + if(pattnr == 0xff) { // arrangement handling + songend = 1; // set end-flag songpos = 0; pattnr = song[songpos]; - } - else if ((pattnr & 128) && (pattnr <= 0xb1)) - { // goto pattern "nr" - songpos = song[songpos] & 127; - pattpos = 0; - pattnr = song[songpos]; - songend = 1; - } - - if (pattnr >= 50 || pattpos >= 64) - { - fprintf (stderr, "hsc: Invalid pattnr (%d) or pattpos (%d)!\n", (int) pattnr, (int) pattpos); - return false; - } + } else + if ((pattnr & 128) && (pattnr <= 0xb1)) { // goto pattern "nr" + songpos = song[songpos] & 127; + pattpos = 0; + pattnr = song[songpos]; + songend = 1; + } - pattoff = pattpos * 9; - for (chan = 0; chan < 9; chan++) - { // handle all channels + pattoff = pattpos*9; + for (chan=0;chan<9;chan++) { // handle all channels note = patterns[pattnr][pattoff].note; effect = patterns[pattnr][pattoff].effect; pattoff++; - if (note & 128) - { // set instrument - setinstr (chan, effect); + if(note & 128) { // set instrument + setinstr(chan,effect); continue; } eff_op = effect & 0x0f; inst = channel[chan].inst; - if (note) + if(note) channel[chan].slide = 0; - switch (effect & 0xf0) - { // effect handling - case 0: // global effect + switch (effect & 0xf0) { // effect handling + case 0: // global effect /* The following fx are unimplemented on purpose: * 02 - Slide Mainvolume up * 03 - Slide Mainvolume down (here: fade in) @@ -130,212 +112,161 @@ ChscPlayer::update () * This is because i've never seen any HSC modules using the fx this way. * All modules use the fx the way, i've implemented it. */ - switch (eff_op) - { - case 1: - pattbreak++; - break; // jump to next pattern - case 3: - fadein = 31; - break; // fade in (divided by 2) - case 5: - mode6 = 1; - break; // 6 voice mode on - case 6: - mode6 = 0; - break; // 6 voice mode off + switch(eff_op) { + case 1: pattbreak++; break; // jump to next pattern + case 3: fadein = 31; break; // fade in (divided by 2) + case 5: mode6 = 1; break; // 6 voice mode on + case 6: mode6 = 0; break; // 6 voice mode off } break; case 0x20: - case 0x10: // manual slides - if (effect & 0x10) - { + case 0x10: // manual slides + if (effect & 0x10) { channel[chan].freq += eff_op; channel[chan].slide += eff_op; - } - else - { + } else { channel[chan].freq -= eff_op; channel[chan].slide -= eff_op; } - if (!note) - setfreq (chan, channel[chan].freq); + if(!note) + setfreq(chan,channel[chan].freq); break; - case 0x50: // set percussion instrument (unimplemented) + case 0x50: // set percussion instrument (unimplemented) break; - case 0x60: // set feedback - opl->write (0xc0 + chan, - (instr[channel[chan].inst][8] & 1) + (eff_op << 1)); + case 0x60: // set feedback + opl->write(0xc0 + chan, (instr[channel[chan].inst][8] & 1) + (eff_op << 1)); break; - case 0xa0: // set carrier volume + case 0xa0: // set carrier volume vol = eff_op << 2; - opl->write (0x43 + op_table[chan], - vol | (instr[channel[chan].inst][2] & ~63)); + opl->write(0x43 + op_table[chan], vol | (instr[channel[chan].inst][2] & ~63)); break; - case 0xb0: // set modulator volume + case 0xb0: // set modulator volume vol = eff_op << 2; if (instr[inst][8] & 1) - opl->write (0x40 + op_table[chan], - vol | (instr[channel[chan].inst][3] & ~63)); + opl->write(0x40 + op_table[chan], vol | (instr[channel[chan].inst][3] & ~63)); else - opl->write (0x40 + op_table[chan], vol | (instr[inst][3] & ~63)); + opl->write(0x40 + op_table[chan],vol | (instr[inst][3] & ~63)); break; - case 0xc0: // set instrument volume + case 0xc0: // set instrument volume db = eff_op << 2; - opl->write (0x43 + op_table[chan], - db | (instr[channel[chan].inst][2] & ~63)); + opl->write(0x43 + op_table[chan], db | (instr[channel[chan].inst][2] & ~63)); if (instr[inst][8] & 1) - opl->write (0x40 + op_table[chan], - db | (instr[channel[chan].inst][3] & ~63)); + opl->write(0x40 + op_table[chan], db | (instr[channel[chan].inst][3] & ~63)); break; - case 0xd0: - pattbreak++; - songpos = eff_op; - songend = 1; - break; // position jump - case 0xf0: // set speed + case 0xd0: pattbreak++; songpos = eff_op; songend = 1; break; // position jump + case 0xf0: // set speed speed = eff_op; del = ++speed; break; } - if (fadein) // fade-in volume setting - setvolume (chan, fadein * 2, fadein * 2); + if(fadein) // fade-in volume setting + setvolume(chan,fadein*2,fadein*2); - if (!note) // note handling + if(!note) // note handling continue; note--; - if ((note == 0x7f - 1) || ((note / 12) & ~7)) - { // pause (7fh) + if ((note == 0x7f-1) || ((note/12) & ~7)) { // pause (7fh) adl_freq[chan] &= ~32; - opl->write (0xb0 + chan, adl_freq[chan]); + opl->write(0xb0 + chan,adl_freq[chan]); continue; } // play the note - if (mtkmode) // imitate MPU-401 Trakker bug + if(mtkmode) // imitate MPU-401 Trakker bug note--; - Okt = ((note / 12) & 7) << 2; + Okt = ((note/12) & 7) << 2; Fnr = note_table[(note % 12)] + instr[inst][11] + channel[chan].slide; channel[chan].freq = Fnr; - if (!mode6 || chan < 6) + if(!mode6 || chan < 6) adl_freq[chan] = Okt | 32; else - adl_freq[chan] = Okt; // never set key for drums - opl->write (0xb0 + chan, 0); - setfreq (chan, Fnr); - if (mode6) - { - switch (chan) - { // play drums - case 6: - opl->write (0xbd, bd & ~16); - bd |= 48; - break; // bass drum - case 7: - opl->write (0xbd, bd & ~1); - bd |= 33; - break; // hihat - case 8: - opl->write (0xbd, bd & ~2); - bd |= 34; - break; // cymbal + adl_freq[chan] = Okt; // never set key for drums + opl->write(0xb0 + chan, 0); + setfreq(chan,Fnr); + if(mode6) { + switch(chan) { // play drums + case 6: opl->write(0xbd,bd & ~16); bd |= 48; break; // bass drum + case 7: opl->write(0xbd,bd & ~1); bd |= 33; break; // hihat + case 8: opl->write(0xbd,bd & ~2); bd |= 34; break; // cymbal } - opl->write (0xbd, bd); + opl->write(0xbd,bd); } } - del = speed; // player speed-timing - if (pattbreak) - { // do post-effect handling - pattpos = 0; // pattern break! - pattbreak = 0; + del = speed; // player speed-timing + if(pattbreak) { // do post-effect handling + pattpos=0; // pattern break! + pattbreak=0; songpos++; songpos %= 50; - if (!songpos) + if(!songpos) songend = 1; - } - else - { + } else { pattpos++; pattpos &= 63; // advance in pattern data - if (!pattpos) - { + if (!pattpos) { songpos++; songpos %= 50; - if (!songpos) + if(!songpos) songend = 1; } } return !songend; // still playing } -void -ChscPlayer::rewind (int subsong) +void ChscPlayer::rewind(int subsong) { - int i; // counter + int i; // counter // rewind HSC player - pattpos = 0; - songpos = 0; - pattbreak = 0; - speed = 2; - del = 1; - songend = 0; - mode6 = 0; - bd = 0; - fadein = 0; - - opl->init (); // reset OPL chip - opl->write (1, 32); - opl->write (8, 128); - opl->write (0xbd, 0); - - for (i = 0; i < 9; i++) - setinstr ((char) i, (char) i); // init channels + pattpos = 0; songpos = 0; pattbreak = 0; speed = 2; + del = 1; songend = 0; mode6 = 0; bd = 0; fadein = 0; + + opl->init(); // reset OPL chip + opl->write(1,32); opl->write(8,128); opl->write(0xbd,0); + + for(i=0;i<9;i++) + setinstr((char) i,(char) i); // init channels } -unsigned int -ChscPlayer::getpatterns () +unsigned int ChscPlayer::getpatterns() { - unsigned char poscnt, pattcnt = 0; + unsigned char poscnt,pattcnt=0; // count patterns - for (poscnt = 0; poscnt < 51 && song[poscnt] != 0xff; poscnt++) - if (song[poscnt] > pattcnt) + for(poscnt=0;poscnt<51 && song[poscnt] != 0xff;poscnt++) + if(song[poscnt] > pattcnt) pattcnt = song[poscnt]; - return (pattcnt + 1); + return (pattcnt+1); } -unsigned int -ChscPlayer::getorders () +unsigned int ChscPlayer::getorders() { unsigned char poscnt; // count positions - for (poscnt = 0; poscnt < 51; poscnt++) - if (song[poscnt] == 0xff) + for(poscnt=0;poscnt<51;poscnt++) + if(song[poscnt] == 0xff) break; return poscnt; } -unsigned int -ChscPlayer::getinstruments () +unsigned int ChscPlayer::getinstruments() { - unsigned char instcnt, instnum = 0, i; - bool isinst; + unsigned char instcnt,instnum=0,i; + bool isinst; // count instruments - for (instcnt = 0; instcnt < 128; instcnt++) - { + for(instcnt=0;instcnt<128;instcnt++) { isinst = false; - for (i = 0; i < 12; i++) - if (instr[instcnt][i]) + for(i=0;i<12;i++) + if(instr[instcnt][i]) isinst = true; - if (isinst) + if(isinst) instnum++; } @@ -344,46 +275,43 @@ ChscPlayer::getinstruments () /*** private methods *************************************/ -void -ChscPlayer::setfreq (unsigned char chan, unsigned short freq) +void ChscPlayer::setfreq(unsigned char chan, unsigned short freq) { adl_freq[chan] = (adl_freq[chan] & ~3) | (freq >> 8); - opl->write (0xa0 + chan, freq & 0xff); - opl->write (0xb0 + chan, adl_freq[chan]); + opl->write(0xa0 + chan, freq & 0xff); + opl->write(0xb0 + chan, adl_freq[chan]); } -void -ChscPlayer::setvolume (unsigned char chan, int volc, int volm) +void ChscPlayer::setvolume(unsigned char chan, int volc, int volm) { unsigned char *ins = instr[channel[chan].inst]; - char op = op_table[chan]; + char op = op_table[chan]; - opl->write (0x43 + op, volc | (ins[2] & ~63)); - if (ins[8] & 1) // carrier - opl->write (0x40 + op, volm | (ins[3] & ~63)); + opl->write(0x43 + op,volc | (ins[2] & ~63)); + if (ins[8] & 1) // carrier + opl->write(0x40 + op,volm | (ins[3] & ~63)); else - opl->write (0x40 + op, ins[3]); // modulator + opl->write(0x40 + op, ins[3]); // modulator } -void -ChscPlayer::setinstr (unsigned char chan, unsigned char insnr) +void ChscPlayer::setinstr(unsigned char chan, unsigned char insnr) { unsigned char *ins = instr[insnr]; - char op = op_table[chan]; + char op = op_table[chan]; - channel[chan].inst = insnr; // set internal instrument - opl->write (0xb0 + chan, 0); // stop old note + channel[chan].inst = insnr; // set internal instrument + opl->write(0xb0 + chan,0); // stop old note // set instrument - opl->write (0xc0 + chan, ins[8]); - opl->write (0x23 + op, ins[0]); // carrier - opl->write (0x20 + op, ins[1]); // modulator - opl->write (0x63 + op, ins[4]); // bits 0..3 = decay; 4..7 = attack - opl->write (0x60 + op, ins[5]); - opl->write (0x83 + op, ins[6]); // 0..3 = release; 4..7 = sustain - opl->write (0x80 + op, ins[7]); - opl->write (0xe3 + op, ins[9]); // bits 0..1 = Wellenform - opl->write (0xe0 + op, ins[10]); - setvolume (chan, ins[2] & 63, ins[3] & 63); + opl->write(0xc0 + chan, ins[8]); + opl->write(0x23 + op, ins[0]); // carrier + opl->write(0x20 + op, ins[1]); // modulator + opl->write(0x63 + op, ins[4]); // bits 0..3 = decay; 4..7 = attack + opl->write(0x60 + op, ins[5]); + opl->write(0x83 + op, ins[6]); // 0..3 = release; 4..7 = sustain + opl->write(0x80 + op, ins[7]); + opl->write(0xe3 + op, ins[9]); // bits 0..1 = Wellenform + opl->write(0xe0 + op, ins[10]); + setvolume(chan, ins[2] & 63, ins[3] & 63); } diff --git a/src/adplug/core/hsc.h b/src/adplug/core/hsc.h index b5a2ae7..9b4d0d7 100644 --- a/src/adplug/core/hsc.h +++ b/src/adplug/core/hsc.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. - * Copyright (C) 1999 - 2002 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp@gmx.net>, et al. + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -31,10 +31,10 @@ class ChscPlayer: public CPlayer ChscPlayer(Copl *newopl): CPlayer(newopl), mtkmode(0) {} - bool load(VFSFile &fd, const CFileProvider &fp); + bool load(const std::string &filename, const CFileProvider &fp); bool update(); void rewind(int subsong); - float getrefresh() { return 18.2f; }; // refresh rate is fixed at 18.2Hz + float getrefresh() { return 18.2f; }; // refresh rate is fixed at 18.2Hz std::string gettype() { return std::string("HSC Adlib Composer / HSC-Tracker"); } unsigned int getpatterns(); @@ -48,23 +48,23 @@ class ChscPlayer: public CPlayer protected: struct hscnote { unsigned char note, effect; - }; // note type in HSC pattern + }; // note type in HSC pattern struct hscchan { - unsigned char inst; // current instrument - signed char slide; // used for manual slide-effects - unsigned short freq; // actual replaying frequency - }; // HSC channel data + unsigned char inst; // current instrument + signed char slide; // used for manual slide-effects + unsigned short freq; // actual replaying frequency + }; // HSC channel data - hscchan channel[9]; // player channel-info - unsigned char instr[128][12]; // instrument data - unsigned char song[0x80]; // song-arrangement (MPU-401 Trakker enhanced) - hscnote patterns[50][64*9]; // pattern data - unsigned char pattpos,songpos, // various bytes & flags + hscchan channel[9]; // player channel-info + unsigned char instr[128][12]; // instrument data + unsigned char song[0x80]; // song-arrangement (MPU-401 Trakker enhanced) + hscnote patterns[50][64*9]; // pattern data + unsigned char pattpos,songpos, // various bytes & flags pattbreak,songend,mode6,bd,fadein; unsigned int speed,del; - unsigned char adl_freq[9]; // adlib frequency registers - int mtkmode; // flag: MPU-401 Trakker mode on/off + unsigned char adl_freq[9]; // adlib frequency registers + int mtkmode; // flag: MPU-401 Trakker mode on/off private: void setfreq(unsigned char chan, unsigned short freq); diff --git a/src/adplug/core/hsp.cc b/src/adplug/core/hsp.cc index e2eaf7a..a4f610c 100644 --- a/src/adplug/core/hsp.cc +++ b/src/adplug/core/hsp.cc @@ -23,64 +23,46 @@ #include "hsp.h" -CPlayer * -ChspLoader::factory (Copl * newopl) +CPlayer *ChspLoader::factory(Copl *newopl) { - return new ChspLoader (newopl); + return new ChspLoader(newopl); } -bool -ChspLoader::load (VFSFile & fd, const CFileProvider & fp) +bool ChspLoader::load(const std::string &filename, const CFileProvider &fp) { - binistream *f = fp.open (fd); - if (!f) - return false; + binistream *f = fp.open(filename); if(!f) return false; unsigned long i, j, orgsize, filesize; unsigned char *cmp, *org; - std::string filename (fd.filename ()); // file validation section - if (!fp.extension (filename, ".hsp")) - { - fp.close (f); - return false; - } + if(!fp.extension(filename, ".hsp")) { fp.close(f); return false; } - filesize = fp.filesize (f); - orgsize = f->readInt (2); - if (orgsize > 59187) - { - fp.close (f); - return false; - } + filesize = fp.filesize(f); + orgsize = f->readInt(2); + if(orgsize > 59187) { fp.close(f); return false; } // load section cmp = new unsigned char[filesize]; - for (i = 0; i < filesize; i++) - cmp[i] = f->readInt (1); - fp.close (f); + for(i = 0; i < filesize; i++) cmp[i] = f->readInt(1); + fp.close(f); org = new unsigned char[orgsize]; - for (i = 0, j = 0; i < filesize; j += cmp[i], i += 2) - { // RLE decompress - if (j >= orgsize) - break; // memory boundary check - memset (org + j, cmp[i + 1], - j + cmp[i] < orgsize ? cmp[i] : orgsize - j - 1); + for(i = 0, j = 0; i < filesize; j += cmp[i], i += 2) { // RLE decompress + if(j >= orgsize) break; // memory boundary check + memset(org + j, cmp[i + 1], j + cmp[i] < orgsize ? cmp[i] : orgsize - j - 1); } - delete[]cmp; + delete [] cmp; - memcpy (instr, org, 128 * 12); // instruments - for (i = 0; i < 128; i++) - { // correct instruments + memcpy(instr, org, 128 * 12); // instruments + for(i = 0; i < 128; i++) { // correct instruments instr[i][2] ^= (instr[i][2] & 0x40) << 1; instr[i][3] ^= (instr[i][3] & 0x40) << 1; instr[i][11] >>= 4; // slide } - memcpy (song, org + 128 * 12, 51); // tracklist - memcpy (patterns, org + 128 * 12 + 51, orgsize - 128 * 12 - 51); // patterns - delete[]org; + memcpy(song, org + 128 * 12, 51); // tracklist + memcpy(patterns, org + 128 * 12 + 51, orgsize - 128 * 12 - 51); // patterns + delete [] org; - rewind (0); + rewind(0); return true; } diff --git a/src/adplug/core/hsp.h b/src/adplug/core/hsp.h index 691220d..4046249 100644 --- a/src/adplug/core/hsp.h +++ b/src/adplug/core/hsp.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -29,11 +29,11 @@ class ChspLoader: public ChscPlayer public: static CPlayer *factory(Copl *newopl); - ChspLoader(Copl *newopl) - : ChscPlayer(newopl) - {}; + ChspLoader(Copl *newopl) + : ChscPlayer(newopl) + {}; - bool load(VFSFile &fd, const CFileProvider &fp); + bool load(const std::string &filename, const CFileProvider &fp); }; #endif diff --git a/src/adplug/core/hybrid.cc b/src/adplug/core/hybrid.cc index 7333c4e..79a6851 100644 --- a/src/adplug/core/hybrid.cc +++ b/src/adplug/core/hybrid.cc @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -31,8 +31,8 @@ #include "hybrid.h" #include "debug.h" -const unsigned char - CxadhybridPlayer::hyb_adlib_registers[99] = { +const unsigned char CxadhybridPlayer::hyb_adlib_registers[99] = +{ 0xE0, 0x60, 0x80, 0x20, 0x40, 0xE3, 0x63, 0x83, 0x23, 0x43, 0xC0, 0xE1, 0x61, 0x81, 0x21, 0x41, 0xE4, 0x64, 0x84, 0x24, 0x44, 0xC1, 0xE2, 0x62, 0x82, 0x22, 0x42, 0xE5, 0x65, 0x85, 0x25, 0x45, 0xC2, @@ -44,46 +44,36 @@ const unsigned char 0xF2, 0x72, 0x92, 0x32, 0x52, 0xF5, 0x75, 0x95, 0x35, 0x55, 0xC8 }; -const unsigned short - CxadhybridPlayer::hyb_notes[98] = { +const unsigned short CxadhybridPlayer::hyb_notes[98] = +{ 0x0000, 0x0000, - 0x016B, 0x0181, 0x0198, 0x01B0, 0x01CA, 0x01E5, 0x0202, 0x0220, 0x0241, - 0x0263, 0x0287, 0x02AE, - 0x056B, 0x0581, 0x0598, 0x05B0, 0x05CA, 0x05E5, 0x0602, 0x0620, 0x0641, - 0x0663, 0x0687, 0x06AE, - 0x096B, 0x0981, 0x0998, 0x09B0, 0x09CA, 0x09E5, 0x0A02, 0x0A20, 0x0A41, - 0x0A63, 0x0A87, 0x0AAE, - 0x0D6B, 0x0D81, 0x0D98, 0x0DB0, 0x0DCA, 0x0DE5, 0x0E02, 0x0E20, 0x0E41, - 0x0E63, 0x0E87, 0x0EAE, - 0x116B, 0x1181, 0x1198, 0x11B0, 0x11CA, 0x11E5, 0x1202, 0x1220, 0x1241, - 0x1263, 0x1287, 0x12AE, - 0x156B, 0x1581, 0x1598, 0x15B0, 0x15CA, 0x15E5, 0x1602, 0x1620, 0x1641, - 0x1663, 0x1687, 0x16AE, - 0x196B, 0x1981, 0x1998, 0x19B0, 0x19CA, 0x19E5, 0x1A02, 0x1A20, 0x1A41, - 0x1A63, 0x1A87, 0x1AAE, - 0x1D6B, 0x1D81, 0x1D98, 0x1DB0, 0x1DCA, 0x1DE5, 0x1E02, 0x1E20, 0x1E41, - 0x1E63, 0x1E87, 0x1EAE + 0x016B, 0x0181, 0x0198, 0x01B0, 0x01CA, 0x01E5, 0x0202, 0x0220, 0x0241, 0x0263, 0x0287, 0x02AE, + 0x056B, 0x0581, 0x0598, 0x05B0, 0x05CA, 0x05E5, 0x0602, 0x0620, 0x0641, 0x0663, 0x0687, 0x06AE, + 0x096B, 0x0981, 0x0998, 0x09B0, 0x09CA, 0x09E5, 0x0A02, 0x0A20, 0x0A41, 0x0A63, 0x0A87, 0x0AAE, + 0x0D6B, 0x0D81, 0x0D98, 0x0DB0, 0x0DCA, 0x0DE5, 0x0E02, 0x0E20, 0x0E41, 0x0E63, 0x0E87, 0x0EAE, + 0x116B, 0x1181, 0x1198, 0x11B0, 0x11CA, 0x11E5, 0x1202, 0x1220, 0x1241, 0x1263, 0x1287, 0x12AE, + 0x156B, 0x1581, 0x1598, 0x15B0, 0x15CA, 0x15E5, 0x1602, 0x1620, 0x1641, 0x1663, 0x1687, 0x16AE, + 0x196B, 0x1981, 0x1998, 0x19B0, 0x19CA, 0x19E5, 0x1A02, 0x1A20, 0x1A41, 0x1A63, 0x1A87, 0x1AAE, + 0x1D6B, 0x1D81, 0x1D98, 0x1DB0, 0x1DCA, 0x1DE5, 0x1E02, 0x1E20, 0x1E41, 0x1E63, 0x1E87, 0x1EAE }; -const unsigned char - CxadhybridPlayer::hyb_default_instrument[11] = { +const unsigned char CxadhybridPlayer::hyb_default_instrument[11] = +{ 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0x00 }; -CPlayer * -CxadhybridPlayer::factory (Copl * newopl) +CPlayer *CxadhybridPlayer::factory(Copl *newopl) { - return new CxadhybridPlayer (newopl); + return new CxadhybridPlayer(newopl); } -bool -CxadhybridPlayer::xadplayer_load () +bool CxadhybridPlayer::xadplayer_load() { - if (xad.fmt != HYBRID) + if(xad.fmt != HYBRID) return false; // load instruments - hyb.inst = (hyb_instrument *) & tune[0]; + hyb.inst = (hyb_instrument *)&tune[0]; // load order hyb.order = &tune[0x1D4]; @@ -91,8 +81,7 @@ CxadhybridPlayer::xadplayer_load () return true; } -void -CxadhybridPlayer::xadplayer_rewind (int subsong) +void CxadhybridPlayer::xadplayer_rewind(int subsong) { int i; @@ -105,34 +94,32 @@ CxadhybridPlayer::xadplayer_rewind (int subsong) plr.speed = 1; // init channel data - for (i = 0; i < 9; i++) + for(i=0;i<9;i++) { - hyb.channel[i].freq = 0x2000; + hyb.channel[i].freq = 0x2000; hyb.channel[i].freq_slide = 0x0000; } // basic OPL init - opl_write (0x01, 0x20); - opl_write (0xBD, 0x40); - opl_write (0x08, 0x00); + opl_write(0x01, 0x20); + opl_write(0xBD, 0x40); + opl_write(0x08, 0x00); // init OPL channels - for (i = 0; i < 9; i++) + for(i=0;i<9;i++) { - for (int j = 0; j < 11; j++) - opl_write (hyb_adlib_registers[i * 11 + j], - 0x00 /* hyb_default_instrument[j] */ ); + for(int j=0;j<11;j++) + opl_write(hyb_adlib_registers[i*11+j], 0x00 /* hyb_default_instrument[j] */ ); - opl_write (0xA0 + i, 0x00); - opl_write (0xB0 + i, 0x20); + opl_write(0xA0+i, 0x00); + opl_write(0xB0+i, 0x20); } } -void -CxadhybridPlayer::xadplayer_update () +void CxadhybridPlayer::xadplayer_update() { - int i, j; - unsigned char patpos, ordpos; + int i,j; + unsigned char patpos,ordpos; if (--hyb.speed_counter) goto update_slides; @@ -143,78 +130,75 @@ CxadhybridPlayer::xadplayer_update () ordpos = hyb.order_pos; // process channels - for (i = 0; i < 9; i++) + for(i=0;i<9;i++) { - unsigned char *pos = - &tune[0xADE + (hyb.order[hyb.order_pos * 9 + i] * 64 * 2) + - (patpos * 2)]; + unsigned char *pos = &tune[0xADE + (hyb.order[hyb.order_pos*9 + i] * 64 * 2) + (patpos * 2)]; // read event unsigned short event = (pos[1] << 8) + pos[0]; #ifdef DEBUG - AdPlug_LogWrite ("track %02X, channel %02X, event %04X:\n", - hyb.order[hyb.order_pos * 9 + i], i, event); + AdPlug_LogWrite("track %02X, channel %02X, event %04X:\n", hyb.order[hyb.order_pos*9 + i], i, event ); #endif // calculate variables - unsigned char note = event >> 9; - unsigned char ins = ((event & 0x01F0) >> 4); - unsigned char slide = event & 0x000F; + unsigned char note = event >> 9; + unsigned char ins = ((event & 0x01F0) >> 4); + unsigned char slide = event & 0x000F; // play event - switch (note) + switch(note) { - case 0x7D: // 0x7D: Set Speed - hyb.speed = event & 0xFF; - break; - case 0x7E: // 0x7E: Jump Position - hyb.order_pos = event & 0xFF; - hyb.pattern_pos = 0x3F; - - // jumpback ? - if (hyb.order_pos <= ordpos) - plr.looping = 1; - - break; - case 0x7F: // 0x7F: Pattern Break - hyb.pattern_pos = 0x3F; - break; - default: - - // is instrument ? - if (ins) - for (j = 0; j < 11; j++) - opl_write (hyb_adlib_registers[i * 11 + j], *((unsigned char *) &hyb.inst[ins - 1] + 7 + j)); // +7 = skip name... - - // is note ? - if (note) - { - hyb.channel[i].freq = hyb_notes[note]; - hyb.channel[i].freq_slide = 0; - } - - // is slide ? - if (slide) - { - hyb.channel[i].freq_slide = (((slide >> 3) * -1) * (slide & 7)) << 1; - - if (slide & 0x80) - slide = -(slide & 7); - } - - // set frequency - if (!(hyb.channel[i].freq & 0x2000)) - { - opl_write (0xA0 + i, hyb.channel[i].freq & 0xFF); - opl_write (0xB0 + i, hyb.channel[i].freq >> 8); - - hyb.channel[i].freq |= 0x2000; - - opl_write (0xA0 + i, hyb.channel[i].freq & 0xFF); - opl_write (0xB0 + i, hyb.channel[i].freq >> 8); - } - - break; + case 0x7D: // 0x7D: Set Speed + hyb.speed = event & 0xFF; + break; + case 0x7E: // 0x7E: Jump Position + hyb.order_pos = event & 0xFF; + hyb.pattern_pos = 0x3F; + + // jumpback ? + if (hyb.order_pos <= ordpos) + plr.looping = 1; + + break; + case 0x7F: // 0x7F: Pattern Break + hyb.pattern_pos = 0x3F; + break; + default: + + // is instrument ? + if (ins) + for(j=0;j<11;j++) + opl_write(hyb_adlib_registers[i*11+j], *((unsigned char *)&hyb.inst[ins-1] + 7 + j)); // +7 = skip name... + + // is note ? + if (note) + { + hyb.channel[i].freq = hyb_notes[note]; + hyb.channel[i].freq_slide = 0; + } + + // is slide ? + if (slide) + { + hyb.channel[i].freq_slide = (((slide >> 3) * -1) * (slide & 7)) << 1; + + if (slide & 0x80) + slide = -(slide & 7); + } + + // set frequency + if (!(hyb.channel[i].freq & 0x2000)) + { + opl_write(0xA0+i, hyb.channel[i].freq & 0xFF); + opl_write(0xB0+i, hyb.channel[i].freq >> 8); + + hyb.channel[i].freq |= 0x2000; + + opl_write(0xA0+i, hyb.channel[i].freq & 0xFF); + opl_write(0xB0+i, hyb.channel[i].freq >> 8); + } + + break; } } @@ -230,39 +214,35 @@ CxadhybridPlayer::xadplayer_update () update_slides: #ifdef DEBUG - AdPlug_LogWrite ("slides:\n"); + AdPlug_LogWrite("slides:\n"); #endif // update fine frequency slides - for (i = 0; i < 9; i++) + for(i=0;i<9;i++) if (hyb.channel[i].freq_slide) { - hyb.channel[i].freq = - (((hyb.channel[i].freq & 0x1FFF) + - hyb.channel[i].freq_slide) & 0x1FFF) | 0x2000; + hyb.channel[i].freq = (((hyb.channel[i].freq & 0x1FFF) + hyb.channel[i].freq_slide) & 0x1FFF) | 0x2000; - opl_write (0xA0 + i, hyb.channel[i].freq & 0xFF); - opl_write (0xB0 + i, hyb.channel[i].freq >> 8); + opl_write(0xA0+i, hyb.channel[i].freq & 0xFF); + opl_write(0xB0+i, hyb.channel[i].freq >> 8); } } -float -CxadhybridPlayer::xadplayer_getrefresh () +float CxadhybridPlayer::xadplayer_getrefresh() { return 50.0f; } -std::string CxadhybridPlayer::xadplayer_gettype () +std::string CxadhybridPlayer::xadplayer_gettype() { - return (std::string ("xad: hybrid player")); + return (std::string("xad: hybrid player")); } -std::string CxadhybridPlayer::xadplayer_getinstrument (unsigned int i) +std::string CxadhybridPlayer::xadplayer_getinstrument(unsigned int i) { - return (std::string (hyb.inst[i].name, 7)); + return (std::string(hyb.inst[i].name,7)); } -unsigned int -CxadhybridPlayer::xadplayer_getinstruments () +unsigned int CxadhybridPlayer::xadplayer_getinstruments() { return 26; } diff --git a/src/adplug/core/hybrid.h b/src/adplug/core/hybrid.h index 256bf69..9a03d0d 100644 --- a/src/adplug/core/hybrid.h +++ b/src/adplug/core/hybrid.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA diff --git a/src/adplug/core/hyp.cc b/src/adplug/core/hyp.cc index 5358a65..f238a2d 100644 --- a/src/adplug/core/hyp.cc +++ b/src/adplug/core/hyp.cc @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -31,8 +31,8 @@ #include "hyp.h" #include "debug.h" -const unsigned char - CxadhypPlayer::hyp_adlib_registers[99] = { +const unsigned char CxadhypPlayer::hyp_adlib_registers[99] = +{ 0x20, 0x23, 0x40, 0x43, 0x60, 0x63, 0x80, 0x83, 0xA0, 0xB0, 0xC0, 0x21, 0x24, 0x41, 0x44, 0x61, 0x64, 0x81, 0x84, 0xA1, 0xB1, 0xC1, 0x22, 0x25, 0x42, 0x45, 0x62, 0x65, 0x82, 0x85, 0xA2, 0xB2, 0xC2, @@ -44,9 +44,9 @@ const unsigned char 0x32, 0x35, 0x52, 0x55, 0x72, 0x75, 0x92, 0x95, 0xA8, 0xB8, 0xC8 }; -const unsigned short - CxadhypPlayer::hyp_notes[73] = { - 0x0000, // by riven +const unsigned short CxadhypPlayer::hyp_notes[73] = +{ + 0x0000, // by riven 0x0956, 0x096B, 0x0980, 0x0998, 0x09B1, 0x09C9, 0x09E5, 0x0A03, 0x0A21, 0x0A41, 0x0A63, 0x0A86, 0x0D56, 0x0D6B, 0x0D80, 0x0D98, 0x0DB1, 0x0DC9, 0x0DE5, 0x0E03, 0x0E21, 0x0E41, 0x0E63, 0x0E86, 0x1156, 0x116B, 0x1180, @@ -57,35 +57,32 @@ const unsigned short 0x1D98, 0x1DB1, 0x1DC9, 0x1DE5, 0x1E03, 0x1E21, 0x1E41, 0x1E63, 0x1E86 }; -CPlayer * -CxadhypPlayer::factory (Copl * newopl) +CPlayer *CxadhypPlayer::factory(Copl *newopl) { - return new CxadhypPlayer (newopl); + return new CxadhypPlayer(newopl); } -void -CxadhypPlayer::xadplayer_rewind (int subsong) +void CxadhypPlayer::xadplayer_rewind(int subsong) { int i; plr.speed = tune[5]; - opl_write (0xBD, 0xC0); + opl_write(0xBD,0xC0); - for (i = 0; i < 9; i++) - adlib[0xB0 + i] = 0; + for(i=0; i<9; i++) + adlib[0xB0+i] = 0; // define instruments - for (i = 0; i < 99; i++) - opl_write (hyp_adlib_registers[i], tune[6 + i]); + for(i=0; i<99; i++) + opl_write(hyp_adlib_registers[i], tune[6+i]); hyp.pointer = 0x69; } -void -CxadhypPlayer::xadplayer_update () +void CxadhypPlayer::xadplayer_update() { - for (int i = 0; i < 9; i++) + for(int i=0; i<9; i++) { unsigned char event = tune[hyp.pointer++]; @@ -96,15 +93,15 @@ CxadhypPlayer::xadplayer_update () unsigned char lofreq = (freq & 0xFF); unsigned char hifreq = (freq >> 8); - opl_write (0xB0 + i, adlib[0xB0 + i]); + opl_write(0xB0+i, adlib[0xB0+i]); if (!(event & 0x40)) { - opl_write (0xA0 + i, lofreq); - opl_write (0xB0 + i, hifreq | 0x20); + opl_write(0xA0+i, lofreq); + opl_write(0xB0+i, hifreq | 0x20); } - adlib[0xB0 + i] &= 0xDF; + adlib[0xB0+i] &= 0xDF; } } @@ -117,13 +114,12 @@ CxadhypPlayer::xadplayer_update () } } -float -CxadhypPlayer::xadplayer_getrefresh () +float CxadhypPlayer::xadplayer_getrefresh() { return 60.0f; } -std::string CxadhypPlayer::xadplayer_gettype () +std::string CxadhypPlayer::xadplayer_gettype() { - return std::string ("xad: hypnosis player"); + return std::string("xad: hypnosis player"); } diff --git a/src/adplug/core/hyp.h b/src/adplug/core/hyp.h index 0ddd54c..f3f6877 100644 --- a/src/adplug/core/hyp.h +++ b/src/adplug/core/hyp.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -35,17 +35,17 @@ protected: unsigned short pointer; } hyp; // - bool xadplayer_load() + bool xadplayer_load() { if(xad.fmt == HYP) - return true; + return true; else - return false; + return false; } - void xadplayer_rewind(int subsong); - void xadplayer_update(); - float xadplayer_getrefresh(); - std::string xadplayer_gettype(); + void xadplayer_rewind(int subsong); + void xadplayer_update(); + float xadplayer_getrefresh(); + std::string xadplayer_gettype(); private: static const unsigned char hyp_adlib_registers[99]; diff --git a/src/adplug/core/imf.cc b/src/adplug/core/imf.cc index 109d6cd..136ce2d 100644 --- a/src/adplug/core/imf.cc +++ b/src/adplug/core/imf.cc @@ -1,6 +1,6 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. - * Copyright (C) 1999 - 2006 Simon Peter <dn.tlp@gmx.net>, et al. + * Copyright (C) 1999 - 2008 Simon Peter <dn.tlp@gmx.net>, et al. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -48,141 +48,115 @@ /*** public methods *************************************/ -CPlayer * -CimfPlayer::factory (Copl * newopl) +CPlayer *CimfPlayer::factory(Copl *newopl) { - return new CimfPlayer (newopl); + return new CimfPlayer(newopl); } -bool -CimfPlayer::load (VFSFile & fd, const CFileProvider & fp) +bool CimfPlayer::load(const std::string &filename, const CFileProvider &fp) { - binistream *f = fp.open (fd); - if (!f) - return false; + binistream *f = fp.open(filename); if(!f) return false; unsigned long fsize, flsize, mfsize = 0; unsigned int i; // file validation section { - char header[5]; - int version; + char header[5]; + int version; - f->readString (header, 5); - version = f->readInt (1); + f->readString(header, 5); + version = f->readInt(1); - if (strncmp (header, "ADLIB", 5) || version != 1) - { - if (!fp.extension (fd.filename (), ".imf") && !fp.extension (fd.filename (), ".wlf")) - { + if(strncmp(header, "ADLIB", 5) || version != 1) { + if(!fp.extension(filename, ".imf") && !fp.extension(filename, ".wlf")) { // It's no IMF file at all - fp.close (f); + fp.close(f); return false; - } - else - f->seek (0); // It's a normal IMF file - } - else - { + } else + f->seek(0); // It's a normal IMF file + } else { // It's a IMF file with header - track_name = f->readString ('\0'); - game_name = f->readString ('\0'); - f->ignore (1); - mfsize = f->pos () + 2; + track_name = f->readString('\0'); + game_name = f->readString('\0'); + f->ignore(1); + mfsize = f->pos() + 2; } } // load section - if (mfsize) - fsize = f->readInt (4); + if(mfsize) + fsize = f->readInt(4); else - fsize = f->readInt (2); - flsize = fp.filesize (f); - if (!fsize) - { // footerless file (raw music data) - if (mfsize) - f->seek (-4, binio::Add); + fsize = f->readInt(2); + flsize = fp.filesize(f); + if(!fsize) { // footerless file (raw music data) + if(mfsize) + f->seek(-4, binio::Add); else - f->seek (-2, binio::Add); + f->seek(-2, binio::Add); size = (flsize - mfsize) / 4; - } - else // file has got a footer + } else // file has got a footer size = fsize / 4; data = new Sdata[size]; - for (i = 0; i < size; i++) - { - data[i].reg = f->readInt (1); - data[i].val = f->readInt (1); - data[i].time = f->readInt (2); + for(i = 0; i < size; i++) { + data[i].reg = f->readInt(1); data[i].val = f->readInt(1); + data[i].time = f->readInt(2); } // read footer, if any - if (fsize && (fsize < flsize - 2 - mfsize)) - { - if (f->readInt (1) == 0x1a) - { + if(fsize && (fsize < flsize - 2 - mfsize)) { + if(f->readInt(1) == 0x1a) { // Adam Nielsen's footer format - track_name = f->readString (); - author_name = f->readString (); - remarks = f->readString (); - } - else - { + track_name = f->readString(); + author_name = f->readString(); + remarks = f->readString(); + } else { // Generic footer unsigned long footerlen = flsize - fsize - 2 - mfsize; footer = new char[footerlen + 1]; - f->readString (footer, footerlen); + f->readString(footer, footerlen); footer[footerlen] = '\0'; // Make ASCIIZ string } } - rate = getrate (fd.filename (), fp, f); - fp.close (f); - rewind (0); + rate = getrate(filename, fp, f); + fp.close(f); + rewind(0); return true; } -bool -CimfPlayer::update () +bool CimfPlayer::update() { - do - { - opl->write (data[pos].reg, data[pos].val); - del = data[pos].time; - pos++; - } while (!del && pos < size); - - if (pos >= size) - { - pos = 0; - songend = true; - } - else - timer = rate / (float) del; - - return !songend; + do { + opl->write(data[pos].reg,data[pos].val); + del = data[pos].time; + pos++; + } while(!del && pos < size); + + if(pos >= size) { + pos = 0; + songend = true; + } + else timer = rate / (float)del; + + return !songend; } -void -CimfPlayer::rewind (int subsong) +void CimfPlayer::rewind(int subsong) { - pos = 0; - del = 0; - timer = rate; - songend = false; - opl->init (); - opl->write (1, 32); // go to OPL2 mode + pos = 0; del = 0; timer = rate; songend = false; + opl->init(); opl->write(1,32); // go to OPL2 mode } -std::string CimfPlayer::gettitle () +std::string CimfPlayer::gettitle() { - std::string title; + std::string title; title = track_name; - if (!track_name.empty () && !game_name.empty ()) + if(!track_name.empty() && !game_name.empty()) title += " - "; title += game_name; @@ -190,14 +164,14 @@ std::string CimfPlayer::gettitle () return title; } -std::string CimfPlayer::getdesc () +std::string CimfPlayer::getdesc() { - std::string desc; + std::string desc; - if (footer) - desc = std::string (footer); + if(footer) + desc = std::string(footer); - if (!remarks.empty () && footer) + if(!remarks.empty() && footer) desc += "\n\n"; desc += remarks; @@ -207,23 +181,17 @@ std::string CimfPlayer::getdesc () /*** private methods *************************************/ -float -CimfPlayer::getrate (const std::string & filename, const CFileProvider & fp, - binistream * f) +float CimfPlayer::getrate(const std::string &filename, const CFileProvider &fp, binistream *f) { - if (db) - { // Database available - f->seek (0, binio::Set); - CClockRecord *record = - (CClockRecord *) db->search (CAdPlugDatabase::CKey (*f)); + if(db) { // Database available + f->seek(0, binio::Set); + CClockRecord *record = (CClockRecord *)db->search(CAdPlugDatabase::CKey(*f)); if (record && record->type == CAdPlugDatabase::CRecord::ClockSpeed) return record->clock; } // Otherwise the database is either unavailable, or there's no entry for this file - if (fp.extension (filename, ".imf")) - return 560.0f; - if (fp.extension (filename, ".wlf")) - return 700.0f; - return 700.0f; // default speed for unknown files that aren't .IMF or .WLF + if (fp.extension(filename, ".imf")) return 560.0f; + if (fp.extension(filename, ".wlf")) return 700.0f; + return 700.0f; // default speed for unknown files that aren't .IMF or .WLF } diff --git a/src/adplug/core/imf.h b/src/adplug/core/imf.h index 9eb3a6e..1ef63dc 100644 --- a/src/adplug/core/imf.h +++ b/src/adplug/core/imf.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2005 Simon Peter <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -29,40 +29,40 @@ class CimfPlayer: public CPlayer public: static CPlayer *factory(Copl *newopl); - CimfPlayer(Copl *newopl) - : CPlayer(newopl), footer(0), data(0) - { } - ~CimfPlayer() - { if(data) delete [] data; if(footer) delete [] footer; }; + CimfPlayer(Copl *newopl) + : CPlayer(newopl), footer(0), data(0) + { } + ~CimfPlayer() + { if(data) delete [] data; if(footer) delete [] footer; }; - bool load(VFSFile &fd, const CFileProvider &fp); - bool update(); - void rewind(int subsong); - float getrefresh() - { return timer; }; + bool load(const std::string &filename, const CFileProvider &fp); + bool update(); + void rewind(int subsong); + float getrefresh() + { return timer; }; - std::string gettype() - { return std::string("IMF File Format"); } - std::string gettitle(); - std::string getauthor() - { return author_name; } - std::string getdesc(); + std::string gettype() + { return std::string("IMF File Format"); } + std::string gettitle(); + std::string getauthor() + { return author_name; } + std::string getdesc(); protected: - unsigned long pos, size; - unsigned short del; - bool songend; - float rate, timer; - char *footer; - std::string track_name, game_name, author_name, remarks; + unsigned long pos, size; + unsigned short del; + bool songend; + float rate, timer; + char *footer; + std::string track_name, game_name, author_name, remarks; - struct Sdata { - unsigned char reg, val; - unsigned short time; - } *data; + struct Sdata { + unsigned char reg, val; + unsigned short time; + } *data; private: - float getrate(const std::string &filename, const CFileProvider &fp, binistream *f); + float getrate(const std::string &filename, const CFileProvider &fp, binistream *f); }; #endif diff --git a/src/adplug/core/jbm.cc b/src/adplug/core/jbm.cc index c965804..2b13341 100644 --- a/src/adplug/core/jbm.cc +++ b/src/adplug/core/jbm.cc @@ -14,7 +14,7 @@ * * 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 Street, Fifth Floor, Boston, MA 02110-1301, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * Johannes Bjerregaard's JBM Adlib Music Format player for AdPlug * Written by Dennis Lindroos <lindroos@nls.fi>, February-March 2007 @@ -63,19 +63,18 @@ CPlayer *CjbmPlayer::factory(Copl *newopl) return new CjbmPlayer(newopl); } -bool CjbmPlayer::load(VFSFile & fd, const CFileProvider & fp) +bool CjbmPlayer::load(const std::string &filename, const CFileProvider &fp) { - binistream *f = fp.open (fd); - std::string filename (fd.filename ()); - int filelen = fp.filesize(f); - int i; + binistream *f = fp.open(filename); if(!f) return false; + int filelen = fp.filesize(f); + int i; if (!filelen || !fp.extension(filename, ".jbm")) goto loaderr; // Allocate memory buffer m[] and read entire file into it m = new unsigned char[filelen]; - if (f->readString((char *)m, filelen) != (unsigned int)filelen) goto loaderr; + if (f->readString((char *)m, filelen) != filelen) goto loaderr; fp.close(f); @@ -126,7 +125,7 @@ bool CjbmPlayer::update() short c, spos, frq; for (c = 0; c < 11; c++) { - if (!voice[c].trkpos) // Unused channel + if (!voice[c].trkpos) // Unused channel continue; if (--voice[c].delay) @@ -142,34 +141,34 @@ bool CjbmPlayer::update() spos = voice[c].seqpos; while(!voice[c].delay) { switch(m[spos]) { - case 0xFD: // Set Instrument - voice[c].instr = m[spos+1]; - set_opl_instrument(c, &voice[c]); - spos+=2; - break; - case 0xFF: // End of Sequence - voice[c].seqno = m[++voice[c].trkpos]; - if (voice[c].seqno == 0xff) { - voice[c].trkpos = voice[c].trkstart; - voice[c].seqno = m[voice[c].trkpos]; - //voicemask &= 0x7ff-(1<<c); - voicemask &= ~(1<<c); - } - spos = voice[c].seqpos = sequences[voice[c].seqno]; - break; - default: // Note Event - if ((m[spos] & 127) > 95) - return 0; - - voice[c].note = m[spos]; - voice[c].vol = m[spos+1]; - voice[c].delay = - (m[spos+2] + (m[spos+3]<<8)) + 1; - - frq = notetable[voice[c].note&127]; - voice[c].frq[0] = (unsigned char)frq; - voice[c].frq[1] = frq >> 8; - spos+=4; + case 0xFD: // Set Instrument + voice[c].instr = m[spos+1]; + set_opl_instrument(c, &voice[c]); + spos+=2; + break; + case 0xFF: // End of Sequence + voice[c].seqno = m[++voice[c].trkpos]; + if (voice[c].seqno == 0xff) { + voice[c].trkpos = voice[c].trkstart; + voice[c].seqno = m[voice[c].trkpos]; + //voicemask &= 0x7ff-(1<<c); + voicemask &= ~(1<<c); + } + spos = voice[c].seqpos = sequences[voice[c].seqno]; + break; + default: // Note Event + if ((m[spos] & 127) > 95) + return 0; + + voice[c].note = m[spos]; + voice[c].vol = m[spos+1]; + voice[c].delay = + (m[spos+2] + (m[spos+3]<<8)) + 1; + + frq = notetable[voice[c].note&127]; + voice[c].frq[0] = (unsigned char)frq; + voice[c].frq[1] = frq >> 8; + spos+=4; } } voice[c].seqpos = spos; @@ -238,14 +237,14 @@ void CjbmPlayer::opl_noteonoff(int channel, JBMVoice *v, bool state) opl->write(0xa0 + perchn_tab[channel-6], voice[channel].frq[0]); opl->write(0xb0 + perchn_tab[channel-6], voice[channel].frq[1]); opl->write(0xbd, - state ? bdreg | percmaskon[channel-6] : - bdreg & percmaskoff[channel-6]); + state ? bdreg | percmaskon[channel-6] : + bdreg & percmaskoff[channel-6]); } else { // Melodic mode or Rhythm mode melodic channels opl->write(0xa0 + channel, voice[channel].frq[0]); opl->write(0xb0 + channel, - state ? voice[channel].frq[1] | 0x20 : - voice[channel].frq[1] & 0x1f); + state ? voice[channel].frq[1] | 0x20 : + voice[channel].frq[1] & 0x1f); } return; } diff --git a/src/adplug/core/jbm.h b/src/adplug/core/jbm.h index cb9e4cb..a1d34d3 100644 --- a/src/adplug/core/jbm.h +++ b/src/adplug/core/jbm.h @@ -14,7 +14,7 @@ * * 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 Street, Fifth Floor, Boston, MA 02110-1301, USA. + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * * jbm.h - JBM Player by Dennis Lindroos <lindroos@nls.fi> */ @@ -32,9 +32,9 @@ class CjbmPlayer: public CPlayer CjbmPlayer(Copl *newopl) : CPlayer(newopl), m(0) { } ~CjbmPlayer() - { if(m != nullptr) delete [] m; } + { if(m != NULL) delete [] m; } - bool load(VFSFile &fd, const CFileProvider &fp); + bool load(const std::string &filename, const CFileProvider &fp); bool update(); void rewind(int subsong); @@ -44,7 +44,7 @@ class CjbmPlayer: public CPlayer std::string gettype() { return std::string(flags&1 ? "JBM Adlib Music [rhythm mode]" : - "JBM Adlib Music"); + "JBM Adlib Music"); } std::string getauthor() { return std::string("Johannes Bjerregaard"); } diff --git a/src/adplug/core/kemuopl.h b/src/adplug/core/kemuopl.h index bdee9d7..86461be 100644 --- a/src/adplug/core/kemuopl.h +++ b/src/adplug/core/kemuopl.h @@ -24,7 +24,9 @@ #define H_ADPLUG_KEMUOPL #include "opl.h" +extern "C" { #include "adlibemu.h" +} class CKemuopl: public Copl { @@ -47,13 +49,13 @@ public: void write(int reg, int val) { if(currChip == 0) - adlib0(reg, val); + adlib0(reg, val); }; void init() {}; private: - bool use16bit,stereo; + bool use16bit,stereo; }; #endif diff --git a/src/adplug/core/ksm.cc b/src/adplug/core/ksm.cc index 9b9bea5..e709323 100644 --- a/src/adplug/core/ksm.cc +++ b/src/adplug/core/ksm.cc @@ -24,396 +24,314 @@ #include "ksm.h" #include "debug.h" -const unsigned int - CksmPlayer::adlibfreq[63] = { +const unsigned int CksmPlayer::adlibfreq[63] = { 0, - 2390, 2411, 2434, 2456, 2480, 2506, 2533, 2562, 2592, 2625, 2659, 2695, - 3414, 3435, 3458, 3480, 3504, 3530, 3557, 3586, 3616, 3649, 3683, 3719, - 4438, 4459, 4482, 4504, 4528, 4554, 4581, 4610, 4640, 4673, 4707, 4743, - 5462, 5483, 5506, 5528, 5552, 5578, 5605, 5634, 5664, 5697, 5731, 5767, - 6486, 6507, 6530, 6552, 6576, 6602, 6629, 6658, 6688, 6721, 6755, 6791, - 7510 -}; + 2390,2411,2434,2456,2480,2506,2533,2562,2592,2625,2659,2695, + 3414,3435,3458,3480,3504,3530,3557,3586,3616,3649,3683,3719, + 4438,4459,4482,4504,4528,4554,4581,4610,4640,4673,4707,4743, + 5462,5483,5506,5528,5552,5578,5605,5634,5664,5697,5731,5767, + 6486,6507,6530,6552,6576,6602,6629,6658,6688,6721,6755,6791, + 7510}; /*** public methods **************************************/ -CPlayer * -CksmPlayer::factory (Copl * newopl) +CPlayer *CksmPlayer::factory(Copl *newopl) { - return new CksmPlayer (newopl); + return new CksmPlayer(newopl); } -bool -CksmPlayer::load (VFSFile & fd, const CFileProvider & fp) +bool CksmPlayer::load(const std::string &filename, const CFileProvider &fp) { - binistream *f; - int i; - std::string filename (fd.filename ()); - char *fn = new char[filename.length () + 9]; + binistream *f; + int i; + char *fn = new char[filename.length() + 9]; // file validation section - if (!fp.extension (filename, ".ksm")) - { - AdPlug_LogWrite ("CksmPlayer::load(,\"%s\"): File doesn't have '.ksm' " - "extension! Rejected!\n", filename.c_str ()); - delete[]fn; + if(!fp.extension(filename, ".ksm")) { + AdPlug_LogWrite("CksmPlayer::load(,\"%s\"): File doesn't have '.ksm' " + "extension! Rejected!\n", filename.c_str()); + delete [] fn; return false; } - AdPlug_LogWrite ("*** CksmPlayer::load(,\"%s\") ***\n", filename.c_str ()); + AdPlug_LogWrite("*** CksmPlayer::load(,\"%s\") ***\n", filename.c_str()); // Load instruments from 'insts.dat' - strcpy (fn, filename.c_str ()); - for (i = strlen (fn) - 1; i >= 0; i--) - if (fn[i] == '/' || fn[i] == '\\') + strcpy(fn, filename.c_str()); + for(i = strlen(fn) - 1; i >= 0; i--) + if(fn[i] == '/' || fn[i] == '\\') break; - strcpy (fn + i + 1, "insts.dat"); - AdPlug_LogWrite ("Instruments file: \"%s\"\n", fn); - VFSFile instfd (fn, "rb"); - f = fp.open (instfd); - delete[]fn; - if (!f) - { - AdPlug_LogWrite ("Couldn't open instruments file! Aborting!\n"); - AdPlug_LogWrite ("--- CksmPlayer::load ---\n"); + strcpy(fn + i + 1, "insts.dat"); + AdPlug_LogWrite("Instruments file: \"%s\"\n", fn); + f = fp.open(fn); + delete [] fn; + if(!f) { + AdPlug_LogWrite("Couldn't open instruments file! Aborting!\n"); + AdPlug_LogWrite("--- CksmPlayer::load ---\n"); return false; } - loadinsts (f); - fp.close (f); + loadinsts(f); + fp.close(f); - f = fp.open (fd); - if (!f) - return false; - for (i = 0; i < 16; i++) - trinst[i] = f->readInt (1); - for (i = 0; i < 16; i++) - trquant[i] = f->readInt (1); - for (i = 0; i < 16; i++) - trchan[i] = f->readInt (1); - f->ignore (16); - for (i = 0; i < 16; i++) - trvol[i] = f->readInt (1); - numnotes = f->readInt (2); - note = new unsigned long[numnotes]; - for (i = 0; i < numnotes; i++) - note[i] = f->readInt (4); - fp.close (f); + f = fp.open(filename); if(!f) return false; + for(i = 0; i < 16; i++) trinst[i] = f->readInt(1); + for(i = 0; i < 16; i++) trquant[i] = f->readInt(1); + for(i = 0; i < 16; i++) trchan[i] = f->readInt(1); + f->ignore(16); + for(i = 0; i < 16; i++) trvol[i] = f->readInt(1); + numnotes = f->readInt(2); + note = new unsigned long [numnotes]; + for(i = 0; i < numnotes; i++) note[i] = f->readInt(4); + fp.close(f); - if (!trchan[11]) - { + if(!trchan[11]) { drumstat = 0; numchans = 9; - } - else - { + } else { drumstat = 32; numchans = 6; } - rewind (0); - AdPlug_LogWrite ("--- CksmPlayer::load ---\n"); + rewind(0); + AdPlug_LogWrite("--- CksmPlayer::load ---\n"); return true; } -bool -CksmPlayer::update () +bool CksmPlayer::update() { - int quanter, chan = 0, drumnum = 0, freq, track, volevel, volval; - unsigned int i, j, bufnum; - unsigned long temp, templong; + int quanter,chan,drumnum,freq,track,volevel,volval; + unsigned int i,j,bufnum; + unsigned long temp,templong; count++; if (count >= countstop) - { - bufnum = 0; - while (count >= countstop) { - templong = note[nownote]; - track = (int) ((templong >> 8) & 15); - if ((templong & 192) == 0) - { - i = 0; - - while ((i < numchans) && - ((chanfreq[i] != (templong & 63)) || - (chantrack[i] != ((templong >> 8) & 15)))) - i++; - if (i < numchans) + bufnum = 0; + while (count >= countstop) { - databuf[bufnum] = (char) 0; - bufnum++; - databuf[bufnum] = (unsigned char) (0xb0 + i); - bufnum++; - databuf[bufnum] = - (unsigned char) ((adlibfreq[templong & 63] >> 8) & 223); - bufnum++; - chanfreq[i] = 0; - chanage[i] = 0; - } - } - else - { - volevel = trvol[track]; - if ((templong & 192) == 128) - { - volevel -= 4; - if (volevel < 0) - volevel = 0; - } - if ((templong & 192) == 192) - { - volevel += 4; - if (volevel > 63) - volevel = 63; - } - if (track < 11) - { - temp = 0; - i = numchans; - for (j = 0; j < numchans; j++) - if ((countstop - chanage[j] >= temp) && (chantrack[j] == track)) + templong = note[nownote]; + track = (int)((templong>>8)&15); + if ((templong&192) == 0) { - temp = countstop - chanage[j]; - i = j; + i = 0; + + while ((i < numchans) && + ((chanfreq[i] != (templong&63)) || + (chantrack[i] != ((templong>>8)&15)))) + i++; + if (i < numchans) + { + databuf[bufnum] = (char)0; bufnum++; + databuf[bufnum] = (unsigned char)(0xb0+i); bufnum++; + databuf[bufnum] = (unsigned char)((adlibfreq[templong&63]>>8)&223); bufnum++; + chanfreq[i] = 0; + chanage[i] = 0; + } } - if (i < numchans) - { - databuf[bufnum] = (char) 0, bufnum++; - databuf[bufnum] = (unsigned char) (0xb0 + i); - bufnum++; - databuf[bufnum] = (unsigned char) 0; - bufnum++; - volval = (inst[trinst[track]][1] & 192) + (volevel ^ 63); - databuf[bufnum] = (char) 0, bufnum++; - databuf[bufnum] = (unsigned char) (0x40 + op_table[i] + 3); - bufnum++; - databuf[bufnum] = (unsigned char) volval; - bufnum++; - databuf[bufnum] = (char) 0, bufnum++; - databuf[bufnum] = (unsigned char) (0xa0 + i); - bufnum++; - databuf[bufnum] = - (unsigned char) (adlibfreq[templong & 63] & 255); - bufnum++; - databuf[bufnum] = (char) 0, bufnum++; - databuf[bufnum] = (unsigned char) (0xb0 + i); - bufnum++; - databuf[bufnum] = - (unsigned char) ((adlibfreq[templong & 63] >> 8) | 32); - bufnum++; - chanfreq[i] = templong & 63; - chanage[i] = countstop; - } - } - else if ((drumstat & 32) > 0) - { - freq = adlibfreq[templong & 63]; - switch (track) - { - case 11: - drumnum = 16; - chan = 6; - freq -= 2048; - break; - case 12: - drumnum = 8; - chan = 7; - freq -= 2048; - break; - case 13: - drumnum = 4; - chan = 8; - break; - case 14: - drumnum = 2; - chan = 8; - break; - case 15: - drumnum = 1; - chan = 7; - freq -= 2048; - break; - } - databuf[bufnum] = (char) 0, bufnum++; - databuf[bufnum] = (unsigned char) (0xa0 + chan); - bufnum++; - databuf[bufnum] = (unsigned char) (freq & 255); - bufnum++; - databuf[bufnum] = (char) 0, bufnum++; - databuf[bufnum] = (unsigned char) (0xb0 + chan); - bufnum++; - databuf[bufnum] = (unsigned char) ((freq >> 8) & 223); - bufnum++; - databuf[bufnum] = (char) 0, bufnum++; - databuf[bufnum] = (unsigned char) (0xbd); - bufnum++; - databuf[bufnum] = (unsigned char) (drumstat & (255 - drumnum)); - bufnum++; - drumstat |= drumnum; - if ((track == 11) || (track == 12) || (track == 14)) - { - volval = (inst[trinst[track]][1] & 192) + (volevel ^ 63); - databuf[bufnum] = (char) 0, bufnum++; - databuf[bufnum] = (unsigned char) (0x40 + op_table[chan] + 3); - bufnum++; - databuf[bufnum] = (unsigned char) (volval); - bufnum++; - } else - { - volval = (inst[trinst[track]][6] & 192) + (volevel ^ 63); - databuf[bufnum] = (char) 0, bufnum++; - databuf[bufnum] = (unsigned char) (0x40 + op_table[chan]); - bufnum++; - databuf[bufnum] = (unsigned char) (volval); - bufnum++; + { + volevel = trvol[track]; + if ((templong&192) == 128) + { + volevel -= 4; + if (volevel < 0) + volevel = 0; + } + if ((templong&192) == 192) + { + volevel += 4; + if (volevel > 63) + volevel = 63; + } + if (track < 11) + { + temp = 0; + i = numchans; + for(j=0;j<numchans;j++) + if ((countstop - chanage[j] >= temp) && (chantrack[j] == track)) + { + temp = countstop - chanage[j]; + i = j; + } + if (i < numchans) + { + databuf[bufnum] = (char)0, bufnum++; + databuf[bufnum] = (unsigned char)(0xb0+i); bufnum++; + databuf[bufnum] = (unsigned char)0; bufnum++; + volval = (inst[trinst[track]][1]&192)+(volevel^63); + databuf[bufnum] = (char)0, bufnum++; + databuf[bufnum] = (unsigned char)(0x40+op_table[i]+3); bufnum++; + databuf[bufnum] = (unsigned char)volval; bufnum++; + databuf[bufnum] = (char)0, bufnum++; + databuf[bufnum] = (unsigned char)(0xa0+i); bufnum++; + databuf[bufnum] = (unsigned char)(adlibfreq[templong&63]&255); bufnum++; + databuf[bufnum] = (char)0, bufnum++; + databuf[bufnum] = (unsigned char)(0xb0+i); bufnum++; + databuf[bufnum] = (unsigned char)((adlibfreq[templong&63]>>8)|32); bufnum++; + chanfreq[i] = templong&63; + chanage[i] = countstop; + } + } + else if ((drumstat&32) > 0) + { + freq = adlibfreq[templong&63]; + switch(track) + { + case 11: drumnum = 16; chan = 6; freq -= 2048; break; + case 12: drumnum = 8; chan = 7; freq -= 2048; break; + case 13: drumnum = 4; chan = 8; break; + case 14: drumnum = 2; chan = 8; break; + case 15: drumnum = 1; chan = 7; freq -= 2048; break; + } + databuf[bufnum] = (char)0, bufnum++; + databuf[bufnum] = (unsigned char)(0xa0+chan); bufnum++; + databuf[bufnum] = (unsigned char)(freq&255); bufnum++; + databuf[bufnum] = (char)0, bufnum++; + databuf[bufnum] = (unsigned char)(0xb0+chan); bufnum++; + databuf[bufnum] = (unsigned char)((freq>>8)&223); bufnum++; + databuf[bufnum] = (char)0, bufnum++; + databuf[bufnum] = (unsigned char)(0xbd); bufnum++; + databuf[bufnum] = (unsigned char)(drumstat&(255-drumnum)); bufnum++; + drumstat |= drumnum; + if ((track == 11) || (track == 12) || (track == 14)) + { + volval = (inst[trinst[track]][1]&192)+(volevel^63); + databuf[bufnum] = (char)0, bufnum++; + databuf[bufnum] = (unsigned char)(0x40+op_table[chan]+3); bufnum++; + databuf[bufnum] = (unsigned char)(volval); bufnum++; + } + else + { + volval = (inst[trinst[track]][6]&192)+(volevel^63); + databuf[bufnum] = (char)0, bufnum++; + databuf[bufnum] = (unsigned char)(0x40+op_table[chan]); bufnum++; + databuf[bufnum] = (unsigned char)(volval); bufnum++; + } + databuf[bufnum] = (char)0, bufnum++; + databuf[bufnum] = (unsigned char)(0xbd); bufnum++; + databuf[bufnum] = (unsigned char)(drumstat); bufnum++; + } + } + nownote++; + if (nownote >= numnotes) { + nownote = 0; + songend = true; } - databuf[bufnum] = (char) 0, bufnum++; - databuf[bufnum] = (unsigned char) (0xbd); - bufnum++; - databuf[bufnum] = (unsigned char) (drumstat); - bufnum++; + templong = note[nownote]; + if (nownote == 0) + count = (templong>>12)-1; + quanter = (240/trquant[(templong>>8)&15]); + countstop = (((templong>>12)+(quanter>>1)) / quanter) * quanter; } - } - nownote++; - if (nownote >= numnotes) - { - nownote = 0; - songend = true; - } - templong = note[nownote]; - if (nownote == 0) - count = (templong >> 12) - 1; - quanter = (240 / trquant[(templong >> 8) & 15]); - countstop = (((templong >> 12) + (quanter >> 1)) / quanter) * quanter; + for(i=0;i<bufnum;i+=3) + opl->write(databuf[i+1],databuf[i+2]); } - for (i = 0; i < bufnum; i += 3) - opl->write (databuf[i + 1], databuf[i + 2]); - } return !songend; } -void -CksmPlayer::rewind (int subsong) +void CksmPlayer::rewind(int subsong) { - unsigned int i, j, k; + unsigned int i,j,k; unsigned char instbuf[11]; unsigned long templong; songend = false; - opl->init (); - opl->write (1, 32); - opl->write (4, 0); - opl->write (8, 0); - opl->write (0xbd, drumstat); + opl->init(); opl->write(1,32); opl->write(4,0); opl->write(8,0); opl->write(0xbd,drumstat); - if (trchan[11] == 1) - { - for (i = 0; i < 11; i++) + if (trchan[11] == 1) { + for(i=0;i<11;i++) instbuf[i] = inst[trinst[11]][i]; - instbuf[1] = ((instbuf[1] & 192) | ((trvol[11]) ^ 63)); - setinst (6, instbuf[0], instbuf[1], instbuf[2], instbuf[3], instbuf[4], - instbuf[5], instbuf[6], instbuf[7], instbuf[8], instbuf[9], - instbuf[10]); - for (i = 0; i < 5; i++) + instbuf[1] = ((instbuf[1]&192)|((trvol[11])^63)); + setinst(6,instbuf[0],instbuf[1],instbuf[2],instbuf[3],instbuf[4],instbuf[5],instbuf[6],instbuf[7],instbuf[8],instbuf[9],instbuf[10]); + for(i=0;i<5;i++) instbuf[i] = inst[trinst[12]][i]; - for (i = 5; i < 11; i++) + for(i=5;i<11;i++) instbuf[i] = inst[trinst[15]][i]; - instbuf[1] = ((instbuf[1] & 192) | ((trvol[12]) ^ 63)); - instbuf[6] = ((instbuf[6] & 192) | ((trvol[15]) ^ 63)); - setinst (7, instbuf[0], instbuf[1], instbuf[2], instbuf[3], instbuf[4], - instbuf[5], instbuf[6], instbuf[7], instbuf[8], instbuf[9], - instbuf[10]); - for (i = 0; i < 5; i++) + instbuf[1] = ((instbuf[1]&192)|((trvol[12])^63)); + instbuf[6] = ((instbuf[6]&192)|((trvol[15])^63)); + setinst(7,instbuf[0],instbuf[1],instbuf[2],instbuf[3],instbuf[4],instbuf[5],instbuf[6],instbuf[7],instbuf[8],instbuf[9],instbuf[10]); + for(i=0;i<5;i++) instbuf[i] = inst[trinst[14]][i]; - for (i = 5; i < 11; i++) + for(i=5;i<11;i++) instbuf[i] = inst[trinst[13]][i]; - instbuf[1] = ((instbuf[1] & 192) | ((trvol[14]) ^ 63)); - instbuf[6] = ((instbuf[6] & 192) | ((trvol[13]) ^ 63)); - setinst (8, instbuf[0], instbuf[1], instbuf[2], instbuf[3], instbuf[4], - instbuf[5], instbuf[6], instbuf[7], instbuf[8], instbuf[9], - instbuf[10]); + instbuf[1] = ((instbuf[1]&192)|((trvol[14])^63)); + instbuf[6] = ((instbuf[6]&192)|((trvol[13])^63)); + setinst(8,instbuf[0],instbuf[1],instbuf[2],instbuf[3],instbuf[4],instbuf[5],instbuf[6],instbuf[7],instbuf[8],instbuf[9],instbuf[10]); } - for (i = 0; i < numchans; i++) - { - chantrack[i] = 0; - chanage[i] = 0; - } + for(i=0;i<numchans;i++) + { + chantrack[i] = 0; + chanage[i] = 0; + } j = 0; - for (i = 0; i < 16; i++) + for(i=0;i<16;i++) if ((trchan[i] > 0) && (j < numchans)) - { - k = trchan[i]; - while ((j < numchans) && (k > 0)) { - chantrack[j] = i; - k--; - j++; + k = trchan[i]; + while ((j < numchans) && (k > 0)) + { + chantrack[j] = i; + k--; + j++; + } } + for(i=0;i<numchans;i++) + { + for(j=0;j<11;j++) + instbuf[j] = inst[trinst[chantrack[i]]][j]; + instbuf[1] = ((instbuf[1]&192)|(63-trvol[chantrack[i]])); + setinst(i,instbuf[0],instbuf[1],instbuf[2],instbuf[3],instbuf[4],instbuf[5],instbuf[6],instbuf[7],instbuf[8],instbuf[9],instbuf[10]); + chanfreq[i] = 0; } - for (i = 0; i < numchans; i++) - { - for (j = 0; j < 11; j++) - instbuf[j] = inst[trinst[chantrack[i]]][j]; - instbuf[1] = ((instbuf[1] & 192) | (63 - trvol[chantrack[i]])); - setinst (i, instbuf[0], instbuf[1], instbuf[2], instbuf[3], instbuf[4], - instbuf[5], instbuf[6], instbuf[7], instbuf[8], instbuf[9], - instbuf[10]); - chanfreq[i] = 0; - } k = 0; templong = *note; - count = (templong >> 12) - 1; - countstop = (templong >> 12) - 1; + count = (templong>>12)-1; + countstop = (templong>>12)-1; nownote = 0; } -std::string CksmPlayer::getinstrument (unsigned int n) +std::string CksmPlayer::getinstrument(unsigned int n) { - if (trchan[n]) - return std::string (instname[trinst[n]]); + if(trchan[n]) + return std::string(instname[trinst[n]]); else - return std::string (); + return std::string(); } /*** private methods *************************************/ -void -CksmPlayer::loadinsts (binistream * f) +void CksmPlayer::loadinsts(binistream *f) { int i, j; - for (i = 0; i < 256; i++) - { - f->readString (instname[i], 20); - for (j = 0; j < 11; j++) - inst[i][j] = f->readInt (1); - f->ignore (2); + for(i = 0; i < 256; i++) { + f->readString(instname[i], 20); + for(j = 0; j < 11; j++) inst[i][j] = f->readInt(1); + f->ignore(2); } } -void -CksmPlayer::setinst (int chan, - unsigned char v0, unsigned char v1, unsigned char v2, - unsigned char v3, unsigned char v4, unsigned char v5, - unsigned char v6, unsigned char v7, unsigned char v8, - unsigned char v9, unsigned char v10) +void CksmPlayer::setinst(int chan, + unsigned char v0,unsigned char v1,unsigned char v2, + unsigned char v3,unsigned char v4,unsigned char v5, + unsigned char v6,unsigned char v7,unsigned char v8, + unsigned char v9,unsigned char v10) { int offs; - opl->write (0xa0 + chan, 0); - opl->write (0xb0 + chan, 0); - opl->write (0xc0 + chan, v10); + opl->write(0xa0+chan,0); + opl->write(0xb0+chan,0); + opl->write(0xc0+chan,v10); offs = op_table[chan]; - opl->write (0x20 + offs, v5); - opl->write (0x40 + offs, v6); - opl->write (0x60 + offs, v7); - opl->write (0x80 + offs, v8); - opl->write (0xe0 + offs, v9); - offs += 3; - opl->write (0x20 + offs, v0); - opl->write (0x40 + offs, v1); - opl->write (0x60 + offs, v2); - opl->write (0x80 + offs, v3); - opl->write (0xe0 + offs, v4); + opl->write(0x20+offs,v5); + opl->write(0x40+offs,v6); + opl->write(0x60+offs,v7); + opl->write(0x80+offs,v8); + opl->write(0xe0+offs,v9); + offs+=3; + opl->write(0x20+offs,v0); + opl->write(0x40+offs,v1); + opl->write(0x60+offs,v2); + opl->write(0x80+offs,v3); + opl->write(0xe0+offs,v4); } diff --git a/src/adplug/core/ksm.h b/src/adplug/core/ksm.h index 3137df9..f97e4c4 100644 --- a/src/adplug/core/ksm.h +++ b/src/adplug/core/ksm.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -26,37 +26,37 @@ class CksmPlayer: public CPlayer public: static CPlayer *factory(Copl *newopl); - CksmPlayer(Copl *newopl) - : CPlayer(newopl), note(0) - { }; - ~CksmPlayer() - { if(note) delete [] note; }; + CksmPlayer(Copl *newopl) + : CPlayer(newopl), note(0) + { }; + ~CksmPlayer() + { if(note) delete [] note; }; - bool load(VFSFile &fd, const CFileProvider &fp); - bool update(); - void rewind(int subsong); - float getrefresh() - { return 240.0f; }; + bool load(const std::string &filename, const CFileProvider &fp); + bool update(); + void rewind(int subsong); + float getrefresh() + { return 240.0f; }; - std::string gettype() - { return std::string("Ken Silverman's Music Format"); }; - unsigned int getinstruments() - { return 16; }; - std::string getinstrument(unsigned int n); + std::string gettype() + { return std::string("Ken Silverman's Music Format"); }; + unsigned int getinstruments() + { return 16; }; + std::string getinstrument(unsigned int n); private: - static const unsigned int adlibfreq[63]; + static const unsigned int adlibfreq[63]; - unsigned long count,countstop,chanage[18],*note; - unsigned short numnotes; - unsigned int nownote,numchans,drumstat; - unsigned char trinst[16],trquant[16],trchan[16],trvol[16],inst[256][11],databuf[2048],chanfreq[18],chantrack[18]; - char instname[256][20]; + unsigned long count,countstop,chanage[18],*note; + unsigned short numnotes; + unsigned int nownote,numchans,drumstat; + unsigned char trinst[16],trquant[16],trchan[16],trvol[16],inst[256][11],databuf[2048],chanfreq[18],chantrack[18]; + char instname[256][20]; - bool songend; + bool songend; - void loadinsts(binistream *f); - void setinst(int chan,unsigned char v0,unsigned char v1,unsigned char v2,unsigned char v3, - unsigned char v4,unsigned char v5,unsigned char v6,unsigned char v7, - unsigned char v8,unsigned char v9,unsigned char v10); + void loadinsts(binistream *f); + void setinst(int chan,unsigned char v0,unsigned char v1,unsigned char v2,unsigned char v3, + unsigned char v4,unsigned char v5,unsigned char v6,unsigned char v7, + unsigned char v8,unsigned char v9,unsigned char v10); }; diff --git a/src/adplug/core/lds.cc b/src/adplug/core/lds.cc index 93789a2..7c87b28 100644 --- a/src/adplug/core/lds.cc +++ b/src/adplug/core/lds.cc @@ -25,8 +25,7 @@ #include "debug.h" // Note frequency table (16 notes / octave) -const unsigned short - CldsPlayer::frequency[] = { +const unsigned short CldsPlayer::frequency[] = { 343, 344, 345, 347, 348, 349, 350, 352, 353, 354, 356, 357, 358, 359, 361, 362, 363, 365, 366, 367, 369, 370, 371, 373, 374, 375, 377, 378, 379, 381, 382, 384, 385, 386, 388, 389, 391, 392, 393, @@ -45,8 +44,7 @@ const unsigned short }; // Vibrato (sine) table -const unsigned char - CldsPlayer::vibtab[] = { +const unsigned char CldsPlayer::vibtab[] = { 0, 13, 25, 37, 50, 62, 74, 86, 98, 109, 120, 131, 142, 152, 162, 171, 180, 189, 197, 205, 212, 219, 225, 231, 236, 240, 244, 247, 250, 252, 254, 255, 255, 255, 254, 252, 250, 247, 244, 240, 236, @@ -55,8 +53,7 @@ const unsigned char }; // Tremolo (sine * sine) table -const unsigned char - CldsPlayer::tremtab[] = { +const unsigned char CldsPlayer::tremtab[] = { 0, 0, 1, 1, 2, 4, 5, 7, 10, 12, 15, 18, 21, 25, 29, 33, 37, 42, 47, 52, 57, 62, 67, 73, 79, 85, 90, 97, 103, 109, 115, 121, 128, 134, 140, 146, 152, 158, 165, 170, 176, 182, 188, 193, 198, 203, 208, @@ -70,627 +67,510 @@ const unsigned char // 'maxsound' is maximum number of patches (instruments) // 'maxpos' is maximum number of entries in position list (orderlist) -const unsigned short - CldsPlayer::maxsound = 0x3f, CldsPlayer::maxpos = 0xff; +const unsigned short CldsPlayer::maxsound = 0x3f, CldsPlayer::maxpos = 0xff; /*** public methods *************************************/ -CldsPlayer::CldsPlayer (Copl * newopl):CPlayer (newopl), soundbank (0), positions (0), -patterns (0) +CldsPlayer::CldsPlayer(Copl *newopl) + : CPlayer(newopl), soundbank(0), positions(0), patterns(0) { } -CldsPlayer::~CldsPlayer () +CldsPlayer::~CldsPlayer() { - if (soundbank) - delete[]soundbank; - if (positions) - delete[]positions; - if (patterns) - delete[]patterns; + if(soundbank) delete [] soundbank; + if(positions) delete [] positions; + if(patterns) delete [] patterns; } -bool -CldsPlayer::load (VFSFile & fd, const CFileProvider & fp) +bool CldsPlayer::load(const std::string &filename, const CFileProvider &fp) { - binistream *f; - unsigned int i, j; - SoundBank *sb; - std::string filename (fd.filename ()); + binistream *f; + unsigned int i, j; + SoundBank *sb; // file validation section (actually just an extension check) - f = fp.open (fd); - if (!f) - return false; - if (!fp.extension (filename, ".lds")) - return false; + if(!fp.extension(filename, ".lds")) return false; + f = fp.open(filename); if(!f) return false; // file load section (header) - mode = f->readInt (1); - if (mode > 2) - { - fp.close (f); - return false; - } - speed = f->readInt (2); - tempo = f->readInt (1); - pattlen = f->readInt (1); - for (i = 0; i < 9; i++) - chandelay[i] = f->readInt (1); - regbd = f->readInt (1); + mode = f->readInt(1); + if(mode > 2) { fp.close(f); return false; } + speed = f->readInt(2); + tempo = f->readInt(1); + pattlen = f->readInt(1); + for(i = 0; i < 9; i++) chandelay[i] = f->readInt(1); + regbd = f->readInt(1); // load patches - numpatch = f->readInt (2); + numpatch = f->readInt(2); soundbank = new SoundBank[numpatch]; - for (i = 0; i < numpatch; i++) - { + for(i = 0; i < numpatch; i++) { sb = &soundbank[i]; - sb->mod_misc = f->readInt (1); - sb->mod_vol = f->readInt (1); - sb->mod_ad = f->readInt (1); - sb->mod_sr = f->readInt (1); - sb->mod_wave = f->readInt (1); - sb->car_misc = f->readInt (1); - sb->car_vol = f->readInt (1); - sb->car_ad = f->readInt (1); - sb->car_sr = f->readInt (1); - sb->car_wave = f->readInt (1); - sb->feedback = f->readInt (1); - sb->keyoff = f->readInt (1); - sb->portamento = f->readInt (1); - sb->glide = f->readInt (1); - sb->finetune = f->readInt (1); - sb->vibrato = f->readInt (1); - sb->vibdelay = f->readInt (1); - sb->mod_trem = f->readInt (1); - sb->car_trem = f->readInt (1); - sb->tremwait = f->readInt (1); - sb->arpeggio = f->readInt (1); - for (j = 0; j < 12; j++) - sb->arp_tab[j] = f->readInt (1); - sb->start = f->readInt (2); - sb->size = f->readInt (2); - sb->fms = f->readInt (1); - sb->transp = f->readInt (2); - sb->midinst = f->readInt (1); - sb->midvelo = f->readInt (1); - sb->midkey = f->readInt (1); - sb->midtrans = f->readInt (1); - sb->middum1 = f->readInt (1); - sb->middum2 = f->readInt (1); + sb->mod_misc = f->readInt(1); sb->mod_vol = f->readInt(1); + sb->mod_ad = f->readInt(1); sb->mod_sr = f->readInt(1); + sb->mod_wave = f->readInt(1); sb->car_misc = f->readInt(1); + sb->car_vol = f->readInt(1); sb->car_ad = f->readInt(1); + sb->car_sr = f->readInt(1); sb->car_wave = f->readInt(1); + sb->feedback = f->readInt(1); sb->keyoff = f->readInt(1); + sb->portamento = f->readInt(1); sb->glide = f->readInt(1); + sb->finetune = f->readInt(1); sb->vibrato = f->readInt(1); + sb->vibdelay = f->readInt(1); sb->mod_trem = f->readInt(1); + sb->car_trem = f->readInt(1); sb->tremwait = f->readInt(1); + sb->arpeggio = f->readInt(1); + for(j = 0; j < 12; j++) sb->arp_tab[j] = f->readInt(1); + sb->start = f->readInt(2); sb->size = f->readInt(2); + sb->fms = f->readInt(1); sb->transp = f->readInt(2); + sb->midinst = f->readInt(1); sb->midvelo = f->readInt(1); + sb->midkey = f->readInt(1); sb->midtrans = f->readInt(1); + sb->middum1 = f->readInt(1); sb->middum2 = f->readInt(1); } // load positions - numposi = f->readInt (2); + numposi = f->readInt(2); positions = new Position[9 * numposi]; - for (i = 0; i < numposi; i++) - for (j = 0; j < 9; j++) - { + for(i = 0; i < numposi; i++) + for(j = 0; j < 9; j++) { /* * patnum is a pointer inside the pattern space, but patterns are 16bit * word fields anyway, so it ought to be an even number (hopefully) and * we can just divide it by 2 to get our array index of 16bit words. */ - positions[i * 9 + j].patnum = f->readInt (2) / 2; - positions[i * 9 + j].transpose = f->readInt (1); + positions[i * 9 + j].patnum = f->readInt(2) / 2; + positions[i * 9 + j].transpose = f->readInt(1); } - AdPlug_LogWrite - ("CldsPlayer::load(\"%s\",fp): loading LOUDNESS file: mode = " - "%d, pattlen = %d, numpatch = %d, numposi = %d\n", filename.c_str (), - mode, pattlen, numpatch, numposi); + AdPlug_LogWrite("CldsPlayer::load(\"%s\",fp): loading LOUDNESS file: mode = " + "%d, pattlen = %d, numpatch = %d, numposi = %d\n", + filename.c_str(), mode, pattlen, numpatch, numposi); // load patterns - f->ignore (2); // ignore # of digital sounds (not played by this player) - patterns = new unsigned short[(fp.filesize (f) - f->pos ()) / 2 + 1]; - for (i = 0; !f->eof (); i++) - patterns[i] = f->readInt (2); + f->ignore(2); // ignore # of digital sounds (not played by this player) + patterns = new unsigned short[(fp.filesize(f) - f->pos()) / 2 + 1]; + for(i = 0; !f->eof(); i++) + patterns[i] = f->readInt(2); - fp.close (f); - rewind (0); + fp.close(f); + rewind(0); return true; } -bool -CldsPlayer::update () +bool CldsPlayer::update() { - unsigned short comword, freq, octave, chan, tune, wibc, tremc, arpreg; - bool vbreak; - unsigned char level, regnum, comhi, comlo; - int i; - Channel *c; + unsigned short comword, freq, octave, chan, tune, wibc, tremc, arpreg; + bool vbreak; + unsigned char level, regnum, comhi, comlo; + int i; + Channel *c; - if (!playing) - return false; + if(!playing) return false; // handle fading - if (fadeonoff) - { - if (fadeonoff <= 128) - { - if (allvolume > fadeonoff || allvolume == 0) + if(fadeonoff) { + if(fadeonoff <= 128) { + if(allvolume > fadeonoff || allvolume == 0) allvolume -= fadeonoff; - else - { + else { allvolume = 1; fadeonoff = 0; - if (hardfade != 0) - { + if(hardfade != 0) { playing = false; hardfade = 0; - for (i = 0; i < 9; i++) + for(i = 0; i < 9; i++) channel[i].keycount = 1; } } - } - else - if ((unsigned int) ((allvolume + (0x100 - fadeonoff)) & 0xff) <= - mainvolume) - allvolume += 0x100 - fadeonoff; - else - { - allvolume = mainvolume; - fadeonoff = 0; - } + } else + if(((allvolume + (0x100 - fadeonoff)) & 0xff) <= mainvolume) + allvolume += 0x100 - fadeonoff; + else { + allvolume = mainvolume; + fadeonoff = 0; + } } // handle channel delay - for (chan = 0; chan < 9; chan++) - { + for(chan = 0; chan < 9; chan++) { c = &channel[chan]; - if (c->chancheat.chandelay) - if (!(--c->chancheat.chandelay)) - playsound (c->chancheat.sound, chan, c->chancheat.high); + if(c->chancheat.chandelay) + if(!(--c->chancheat.chandelay)) + playsound(c->chancheat.sound, chan, c->chancheat.high); } // handle notes - if (!tempo_now) - { + if(!tempo_now) { vbreak = false; - for (chan = 0; chan < 9; chan++) - { + for(chan = 0; chan < 9; chan++) { c = &channel[chan]; - if (!c->packwait) - { - unsigned short patnum = positions[posplay * 9 + chan].patnum; - unsigned char transpose = positions[posplay * 9 + chan].transpose; + if(!c->packwait) { + unsigned short patnum = positions[posplay * 9 + chan].patnum; + unsigned char transpose = positions[posplay * 9 + chan].transpose; comword = patterns[patnum + c->packpos]; - comhi = comword >> 8; - comlo = comword & 0xff; - if (comword) - { - if (comhi == 0x80) - { + comhi = comword >> 8; comlo = comword & 0xff; + if(comword) { + if(comhi == 0x80) c->packwait = comlo; - } - else if (comhi >= 0x80) - { - switch (comhi) - { - case 0xff: - c->volcar = (((c->volcar & 0x3f) * comlo) >> 6) & 0x3f; - if (fmchip[0xc0 + chan] & 1) - c->volmod = (((c->volmod & 0x3f) * comlo) >> 6) & 0x3f; - break; - case 0xfe: - tempo = comword & 0x3f; - break; - case 0xfd: - c->nextvol = comlo; - break; - case 0xfc: - playing = false; - // in real player there's also full keyoff here, but we don't need it - break; - case 0xfb: - c->keycount = 1; - break; - case 0xfa: - vbreak = true; - jumppos = (posplay + 1) & maxpos; - break; - case 0xf9: - vbreak = true; - jumppos = comlo & maxpos; - jumping = 1; - if (jumppos < posplay) - songlooped = true; - break; - case 0xf8: - c->lasttune = 0; - break; - case 0xf7: - c->vibwait = 0; - // PASCAL: c->vibspeed = ((comlo >> 4) & 15) + 2; - c->vibspeed = (comlo >> 4) + 2; - c->vibrate = (comlo & 15) + 1; - break; - case 0xf6: - c->glideto = comlo; - break; - case 0xf5: - c->finetune = comlo; - break; - case 0xf4: - if (!hardfade) - { - allvolume = mainvolume = comlo; - fadeonoff = 0; - } - break; - case 0xf3: - if (!hardfade) - fadeonoff = comlo; - break; - case 0xf2: - c->trmstay = comlo; - break; - case 0xf1: // panorama - case 0xf0: // progch - // MIDI commands (unhandled) - AdPlug_LogWrite - ("CldsPlayer(): not handling MIDI command 0x%x, " - "value = 0x%x\n", comhi); - break; - default: - if (comhi < 0xa0) - c->glideto = comhi & 0x1f; - else - AdPlug_LogWrite - ("CldsPlayer(): unknown command 0x%x encountered!" - " value = 0x%x\n", comhi, comlo); - break; - } - } else - { - unsigned char sound; - unsigned short high; - signed char transp = transpose & 127; - - /* - * Originally, in assembler code, the player first shifted - * logically left the transpose byte by 1 and then shifted - * arithmetically right the same byte to achieve the final, - * signed transpose value. Since we can't do arithmetic shifts - * in C, we just duplicate the 7th bit into the 8th one and - * discard the 8th one completely. - */ - - if (transpose & 64) - transp |= 128; - - if (transpose & 128) - { - sound = (comlo + transp) & maxsound; - high = comhi << 4; - } - else - { - sound = comlo & maxsound; - high = (comhi + transp) << 4; - } - - /* - PASCAL: - sound = comlo & maxsound; - high = (comhi + (((transpose + 0x24) & 0xff) - 0x24)) << 4; - */ + if(comhi >= 0x80) { + switch(comhi) { + case 0xff: + c->volcar = (((c->volcar & 0x3f) * comlo) >> 6) & 0x3f; + if(fmchip[0xc0 + chan] & 1) + c->volmod = (((c->volmod & 0x3f) * comlo) >> 6) & 0x3f; + break; + case 0xfe: + tempo = comword & 0x3f; + break; + case 0xfd: + c->nextvol = comlo; + break; + case 0xfc: + playing = false; + // in real player there's also full keyoff here, but we don't need it + break; + case 0xfb: + c->keycount = 1; + break; + case 0xfa: + vbreak = true; + jumppos = (posplay + 1) & maxpos; + break; + case 0xf9: + vbreak = true; + jumppos = comlo & maxpos; + jumping = 1; + if(jumppos < posplay) songlooped = true; + break; + case 0xf8: + c->lasttune = 0; + break; + case 0xf7: + c->vibwait = 0; + // PASCAL: c->vibspeed = ((comlo >> 4) & 15) + 2; + c->vibspeed = (comlo >> 4) + 2; + c->vibrate = (comlo & 15) + 1; + break; + case 0xf6: + c->glideto = comlo; + break; + case 0xf5: + c->finetune = comlo; + break; + case 0xf4: + if(!hardfade) { + allvolume = mainvolume = comlo; + fadeonoff = 0; + } + break; + case 0xf3: + if(!hardfade) fadeonoff = comlo; + break; + case 0xf2: + c->trmstay = comlo; + break; + case 0xf1: // panorama + case 0xf0: // progch + // MIDI commands (unhandled) + AdPlug_LogWrite("CldsPlayer(): not handling MIDI command 0x%x, " + "value = 0x%x\n", comhi); + break; + default: + if(comhi < 0xa0) + c->glideto = comhi & 0x1f; + else + AdPlug_LogWrite("CldsPlayer(): unknown command 0x%x encountered!" + " value = 0x%x\n", comhi, comlo); + break; + } + } else { + unsigned char sound; + unsigned short high; + signed char transp = transpose & 127; + + /* + * Originally, in assembler code, the player first shifted + * logically left the transpose byte by 1 and then shifted + * arithmetically right the same byte to achieve the final, + * signed transpose value. Since we can't do arithmetic shifts + * in C, we just duplicate the 7th bit into the 8th one and + * discard the 8th one completely. + */ + + if(transpose & 64) transp |= 128; + + if(transpose & 128) { + sound = (comlo + transp) & maxsound; + high = comhi << 4; + } else { + sound = comlo & maxsound; + high = (comhi + transp) << 4; + } - if (!chandelay[chan]) - playsound (sound, chan, high); - else - { - c->chancheat.chandelay = chandelay[chan]; - c->chancheat.sound = sound; - c->chancheat.high = high; + /* + PASCAL: + sound = comlo & maxsound; + high = (comhi + (((transpose + 0x24) & 0xff) - 0x24)) << 4; + */ + + if(!chandelay[chan]) + playsound(sound, chan, high); + else { + c->chancheat.chandelay = chandelay[chan]; + c->chancheat.sound = sound; + c->chancheat.high = high; + } } - } } c->packpos++; - } - else + } else c->packwait--; } tempo_now = tempo; /* - The continue table is updated here, but this is only used in the - original player, which can be paused in the middle of a song and then - unpaused. Since AdPlug does all this for us automatically, we don't - have a continue table here. The continue table update code is noted - here for reference only. - - if(!pattplay) { - conttab[speed & maxcont].position = posplay & 0xff; - conttab[speed & maxcont].tempo = tempo; - } - */ + The continue table is updated here, but this is only used in the + original player, which can be paused in the middle of a song and then + unpaused. Since AdPlug does all this for us automatically, we don't + have a continue table here. The continue table update code is noted + here for reference only. + + if(!pattplay) { + conttab[speed & maxcont].position = posplay & 0xff; + conttab[speed & maxcont].tempo = tempo; + } + */ pattplay++; - if (vbreak) - { + if(vbreak) { pattplay = 0; - for (i = 0; i < 9; i++) - channel[i].packpos = channel[i].packwait = 0; + for(i = 0; i < 9; i++) channel[i].packpos = channel[i].packwait = 0; posplay = jumppos; - } - else if (pattplay >= pattlen) - { - pattplay = 0; - for (i = 0; i < 9; i++) - channel[i].packpos = channel[i].packwait = 0; - posplay = (posplay + 1) & maxpos; - } - } - else + } else + if(pattplay >= pattlen) { + pattplay = 0; + for(i = 0; i < 9; i++) channel[i].packpos = channel[i].packwait = 0; + posplay = (posplay + 1) & maxpos; + } + } else tempo_now--; // make effects - for (chan = 0; chan < 9; chan++) - { + for(chan = 0; chan < 9; chan++) { c = &channel[chan]; regnum = op_table[chan]; - if (c->keycount > 0) - { - if (c->keycount == 1) - setregs_adv (0xb0 + chan, 0xdf, 0); + if(c->keycount > 0) { + if(c->keycount == 1) + setregs_adv(0xb0 + chan, 0xdf, 0); c->keycount--; } // arpeggio - if (c->arp_size == 0) + if(c->arp_size == 0) arpreg = 0; - else - { + else { arpreg = c->arp_tab[c->arp_pos] << 4; - if (arpreg == 0x800) - { - if (c->arp_pos > 0) - c->arp_tab[0] = c->arp_tab[c->arp_pos - 1]; - c->arp_size = 1; - c->arp_pos = 0; + if(arpreg == 0x800) { + if(c->arp_pos > 0) c->arp_tab[0] = c->arp_tab[c->arp_pos - 1]; + c->arp_size = 1; c->arp_pos = 0; arpreg = c->arp_tab[0] << 4; } - if (c->arp_count == c->arp_speed) - { + if(c->arp_count == c->arp_speed) { c->arp_pos++; - if (c->arp_pos >= c->arp_size) - c->arp_pos = 0; + if(c->arp_pos >= c->arp_size) c->arp_pos = 0; c->arp_count = 0; - } - else + } else c->arp_count++; } // glide & portamento - if (c->lasttune && (c->lasttune != c->gototune)) - { - if (c->lasttune > c->gototune) - { - if (c->lasttune - c->gototune < c->portspeed) + if(c->lasttune && (c->lasttune != c->gototune)) { + if(c->lasttune > c->gototune) { + if(c->lasttune - c->gototune < c->portspeed) c->lasttune = c->gototune; else c->lasttune -= c->portspeed; - } - else - { - if (c->gototune - c->lasttune < c->portspeed) + } else { + if(c->gototune - c->lasttune < c->portspeed) c->lasttune = c->gototune; else c->lasttune += c->portspeed; } - if (arpreg >= 0x800) + if(arpreg >= 0x800) arpreg = c->lasttune - (arpreg ^ 0xff0) - 16; else arpreg += c->lasttune; freq = frequency[arpreg % (12 * 16)]; octave = arpreg / (12 * 16) - 1; - setregs (0xa0 + chan, freq & 0xff); - setregs_adv (0xb0 + chan, 0x20, ((octave << 2) + (freq >> 8)) & 0xdf); - } - else - { + setregs(0xa0 + chan, freq & 0xff); + setregs_adv(0xb0 + chan, 0x20, ((octave << 2) + (freq >> 8)) & 0xdf); + } else { // vibrato - if (!c->vibwait) - { - if (c->vibrate) - { + if(!c->vibwait) { + if(c->vibrate) { wibc = vibtab[c->vibcount & 0x3f] * c->vibrate; - if ((c->vibcount & 0x40) == 0) + if((c->vibcount & 0x40) == 0) tune = c->lasttune + (wibc >> 8); else tune = c->lasttune - (wibc >> 8); - if (arpreg >= 0x800) + if(arpreg >= 0x800) tune = tune - (arpreg ^ 0xff0) - 16; else tune += arpreg; freq = frequency[tune % (12 * 16)]; octave = tune / (12 * 16) - 1; - setregs (0xa0 + chan, freq & 0xff); - setregs_adv (0xb0 + chan, 0x20, - ((octave << 2) + (freq >> 8)) & 0xdf); + setregs(0xa0 + chan, freq & 0xff); + setregs_adv(0xb0 + chan, 0x20, ((octave << 2) + (freq >> 8)) & 0xdf); c->vibcount += c->vibspeed; - } - else if (c->arp_size != 0) - { // no vibrato, just arpeggio - if (arpreg >= 0x800) - tune = c->lasttune - (arpreg ^ 0xff0) - 16; - else - tune = c->lasttune + arpreg; + } else + if(c->arp_size != 0) { // no vibrato, just arpeggio + if(arpreg >= 0x800) + tune = c->lasttune - (arpreg ^ 0xff0) - 16; + else + tune = c->lasttune + arpreg; - freq = frequency[tune % (12 * 16)]; - octave = tune / (12 * 16) - 1; - setregs (0xa0 + chan, freq & 0xff); - setregs_adv (0xb0 + chan, 0x20, - ((octave << 2) + (freq >> 8)) & 0xdf); - } - } - else - { // no vibrato, just arpeggio + freq = frequency[tune % (12 * 16)]; + octave = tune / (12 * 16) - 1; + setregs(0xa0 + chan, freq & 0xff); + setregs_adv(0xb0 + chan, 0x20, ((octave << 2) + (freq >> 8)) & 0xdf); + } + } else { // no vibrato, just arpeggio c->vibwait--; - if (c->arp_size != 0) - { - if (arpreg >= 0x800) + if(c->arp_size != 0) { + if(arpreg >= 0x800) tune = c->lasttune - (arpreg ^ 0xff0) - 16; else tune = c->lasttune + arpreg; freq = frequency[tune % (12 * 16)]; octave = tune / (12 * 16) - 1; - setregs (0xa0 + chan, freq & 0xff); - setregs_adv (0xb0 + chan, 0x20, - ((octave << 2) + (freq >> 8)) & 0xdf); + setregs(0xa0 + chan, freq & 0xff); + setregs_adv(0xb0 + chan, 0x20, ((octave << 2) + (freq >> 8)) & 0xdf); } } } // tremolo (modulator) - if (!c->trmwait) - { - if (c->trmrate) - { + if(!c->trmwait) { + if(c->trmrate) { tremc = tremtab[c->trmcount & 0x7f] * c->trmrate; - if ((tremc >> 8) <= (c->volmod & 0x3f)) + if((tremc >> 8) <= (c->volmod & 0x3f)) level = (c->volmod & 0x3f) - (tremc >> 8); else level = 0; - if (allvolume != 0 && (fmchip[0xc0 + chan] & 1)) - setregs_adv (0x40 + regnum, 0xc0, - ((level * allvolume) >> 8) ^ 0x3f); + if(allvolume != 0 && (fmchip[0xc0 + chan] & 1)) + setregs_adv(0x40 + regnum, 0xc0, ((level * allvolume) >> 8) ^ 0x3f); else - setregs_adv (0x40 + regnum, 0xc0, level ^ 0x3f); + setregs_adv(0x40 + regnum, 0xc0, level ^ 0x3f); c->trmcount += c->trmspeed; - } - else if (allvolume != 0 && (fmchip[0xc0 + chan] & 1)) - setregs_adv (0x40 + regnum, 0xc0, - ((((c->volmod & 0x3f) * allvolume) >> 8) ^ 0x3f) & 0x3f); - else - setregs_adv (0x40 + regnum, 0xc0, (c->volmod ^ 0x3f) & 0x3f); - } - else - { + } else + if(allvolume != 0 && (fmchip[0xc0 + chan] & 1)) + setregs_adv(0x40 + regnum, 0xc0, ((((c->volmod & 0x3f) * allvolume) >> 8) ^ 0x3f) & 0x3f); + else + setregs_adv(0x40 + regnum, 0xc0, (c->volmod ^ 0x3f) & 0x3f); + } else { c->trmwait--; - if (allvolume != 0 && (fmchip[0xc0 + chan] & 1)) - setregs_adv (0x40 + regnum, 0xc0, - ((((c->volmod & 0x3f) * allvolume) >> 8) ^ 0x3f) & 0x3f); + if(allvolume != 0 && (fmchip[0xc0 + chan] & 1)) + setregs_adv(0x40 + regnum, 0xc0, ((((c->volmod & 0x3f) * allvolume) >> 8) ^ 0x3f) & 0x3f); } // tremolo (carrier) - if (!c->trcwait) - { - if (c->trcrate) - { + if(!c->trcwait) { + if(c->trcrate) { tremc = tremtab[c->trccount & 0x7f] * c->trcrate; - if ((tremc >> 8) <= (c->volcar & 0x3f)) + if((tremc >> 8) <= (c->volcar & 0x3f)) level = (c->volcar & 0x3f) - (tremc >> 8); else level = 0; - if (allvolume != 0) - setregs_adv (0x43 + regnum, 0xc0, - ((level * allvolume) >> 8) ^ 0x3f); + if(allvolume != 0) + setregs_adv(0x43 + regnum, 0xc0, ((level * allvolume) >> 8) ^ 0x3f); else - setregs_adv (0x43 + regnum, 0xc0, level ^ 0x3f); + setregs_adv(0x43 + regnum, 0xc0, level ^ 0x3f); c->trccount += c->trcspeed; - } - else if (allvolume != 0) - setregs_adv (0x43 + regnum, 0xc0, - ((((c->volcar & 0x3f) * allvolume) >> 8) ^ 0x3f) & 0x3f); - else - setregs_adv (0x43 + regnum, 0xc0, (c->volcar ^ 0x3f) & 0x3f); - } - else - { + } else + if(allvolume != 0) + setregs_adv(0x43 + regnum, 0xc0, ((((c->volcar & 0x3f) * allvolume) >> 8) ^ 0x3f) & 0x3f); + else + setregs_adv(0x43 + regnum, 0xc0, (c->volcar ^ 0x3f) & 0x3f); + } else { c->trcwait--; - if (allvolume != 0) - setregs_adv (0x43 + regnum, 0xc0, - ((((c->volcar & 0x3f) * allvolume) >> 8) ^ 0x3f) & 0x3f); + if(allvolume != 0) + setregs_adv(0x43 + regnum, 0xc0, ((((c->volcar & 0x3f) * allvolume) >> 8) ^ 0x3f) & 0x3f); } } return (!playing || songlooped) ? false : true; } -void -CldsPlayer::rewind (int subsong) +void CldsPlayer::rewind(int subsong) { int i; // init all with 0 - tempo_now = 3; - playing = true; - songlooped = false; + tempo_now = 3; playing = true; songlooped = false; jumping = fadeonoff = allvolume = hardfade = pattplay = posplay = jumppos = mainvolume = 0; - memset (channel, 0, sizeof (channel)); - memset (fmchip, 0, sizeof (fmchip)); + memset(channel, 0, sizeof(channel)); + memset(fmchip, 0, sizeof(fmchip)); // OPL2 init - opl->init (); // Reset OPL chip - opl->write (1, 0x20); - opl->write (8, 0); - opl->write (0xbd, regbd); - - for (i = 0; i < 9; i++) - { - opl->write (0x20 + op_table[i], 0); - opl->write (0x23 + op_table[i], 0); - opl->write (0x40 + op_table[i], 0x3f); - opl->write (0x43 + op_table[i], 0x3f); - opl->write (0x60 + op_table[i], 0xff); - opl->write (0x63 + op_table[i], 0xff); - opl->write (0x80 + op_table[i], 0xff); - opl->write (0x83 + op_table[i], 0xff); - opl->write (0xe0 + op_table[i], 0); - opl->write (0xe3 + op_table[i], 0); - opl->write (0xa0 + i, 0); - opl->write (0xb0 + i, 0); - opl->write (0xc0 + i, 0); + opl->init(); // Reset OPL chip + opl->write(1, 0x20); + opl->write(8, 0); + opl->write(0xbd, regbd); + + for(i = 0; i < 9; i++) { + opl->write(0x20 + op_table[i], 0); + opl->write(0x23 + op_table[i], 0); + opl->write(0x40 + op_table[i], 0x3f); + opl->write(0x43 + op_table[i], 0x3f); + opl->write(0x60 + op_table[i], 0xff); + opl->write(0x63 + op_table[i], 0xff); + opl->write(0x80 + op_table[i], 0xff); + opl->write(0x83 + op_table[i], 0xff); + opl->write(0xe0 + op_table[i], 0); + opl->write(0xe3 + op_table[i], 0); + opl->write(0xa0 + i, 0); + opl->write(0xb0 + i, 0); + opl->write(0xc0 + i, 0); } } /*** private methods *************************************/ -void -CldsPlayer::playsound (int inst_number, int channel_number, int tunehigh) +void CldsPlayer::playsound(int inst_number, int channel_number, int tunehigh) { - if ((unsigned int)inst_number > numpatch-1) { - return; - } - Channel *c = &channel[channel_number]; // current channel - SoundBank *i = &soundbank[inst_number]; // current instrument - unsigned int regnum = op_table[channel_number]; // channel's OPL2 register - unsigned char volcalc, octave; - unsigned short freq; + Channel *c = &channel[channel_number]; // current channel + SoundBank *i = &soundbank[inst_number]; // current instrument + unsigned int regnum = op_table[channel_number]; // channel's OPL2 register + unsigned char volcalc, octave; + unsigned short freq; // set fine tune tunehigh += ((i->finetune + c->finetune + 0x80) & 0xff) - 0x80; // arpeggio handling - if (!i->arpeggio) - { - unsigned short arpcalc = i->arp_tab[0] << 4; + if(!i->arpeggio) { + unsigned short arpcalc = i->arp_tab[0] << 4; - if (arpcalc > 0x800) + if(arpcalc > 0x800) tunehigh = tunehigh - (arpcalc ^ 0xff0) - 16; else tunehigh += arpcalc; } // glide handling - if (c->glideto != 0) - { + if(c->glideto != 0) { c->gototune = tunehigh; c->portspeed = c->glideto; c->glideto = c->finetune = 0; @@ -698,83 +578,69 @@ CldsPlayer::playsound (int inst_number, int channel_number, int tunehigh) } // set modulator registers - setregs (0x20 + regnum, i->mod_misc); + setregs(0x20 + regnum, i->mod_misc); volcalc = i->mod_vol; - if (!c->nextvol || !(i->feedback & 1)) + if(!c->nextvol || !(i->feedback & 1)) c->volmod = volcalc; else c->volmod = (volcalc & 0xc0) | ((((volcalc & 0x3f) * c->nextvol) >> 6)); - if ((i->feedback & 1) == 1 && allvolume != 0) - setregs (0x40 + regnum, - ((c-> - volmod & 0xc0) | (((c->volmod & 0x3f) * - allvolume) >> 8)) ^ 0x3f); + if((i->feedback & 1) == 1 && allvolume != 0) + setregs(0x40 + regnum, ((c->volmod & 0xc0) | (((c->volmod & 0x3f) * allvolume) >> 8)) ^ 0x3f); else - setregs (0x40 + regnum, c->volmod ^ 0x3f); - setregs (0x60 + regnum, i->mod_ad); - setregs (0x80 + regnum, i->mod_sr); - setregs (0xe0 + regnum, i->mod_wave); + setregs(0x40 + regnum, c->volmod ^ 0x3f); + setregs(0x60 + regnum, i->mod_ad); + setregs(0x80 + regnum, i->mod_sr); + setregs(0xe0 + regnum, i->mod_wave); // Set carrier registers - setregs (0x23 + regnum, i->car_misc); + setregs(0x23 + regnum, i->car_misc); volcalc = i->car_vol; - if (!c->nextvol) + if(!c->nextvol) c->volcar = volcalc; else c->volcar = (volcalc & 0xc0) | ((((volcalc & 0x3f) * c->nextvol) >> 6)); - if (allvolume) - setregs (0x43 + regnum, - ((c-> - volcar & 0xc0) | (((c->volcar & 0x3f) * - allvolume) >> 8)) ^ 0x3f); + if(allvolume) + setregs(0x43 + regnum, ((c->volcar & 0xc0) | (((c->volcar & 0x3f) * allvolume) >> 8)) ^ 0x3f); else - setregs (0x43 + regnum, c->volcar ^ 0x3f); - setregs (0x63 + regnum, i->car_ad); - setregs (0x83 + regnum, i->car_sr); - setregs (0xe3 + regnum, i->car_wave); - setregs (0xc0 + channel_number, i->feedback); - setregs_adv (0xb0 + channel_number, 0xdf, 0); // key off + setregs(0x43 + regnum, c->volcar ^ 0x3f); + setregs(0x63 + regnum, i->car_ad); + setregs(0x83 + regnum, i->car_sr); + setregs(0xe3 + regnum, i->car_wave); + setregs(0xc0 + channel_number, i->feedback); + setregs_adv(0xb0 + channel_number, 0xdf, 0); // key off freq = frequency[tunehigh % (12 * 16)]; octave = tunehigh / (12 * 16) - 1; - if (!i->glide) - { - if (!i->portamento || !c->lasttune) - { - setregs (0xa0 + channel_number, freq & 0xff); - setregs (0xb0 + channel_number, (octave << 2) + 0x20 + (freq >> 8)); + if(!i->glide) { + if(!i->portamento || !c->lasttune) { + setregs(0xa0 + channel_number, freq & 0xff); + setregs(0xb0 + channel_number, (octave << 2) + 0x20 + (freq >> 8)); c->lasttune = c->gototune = tunehigh; - } - else - { + } else { c->gototune = tunehigh; c->portspeed = i->portamento; - setregs_adv (0xb0 + channel_number, 0xdf, 0x20); // key on + setregs_adv(0xb0 + channel_number, 0xdf, 0x20); // key on } - } - else - { - setregs (0xa0 + channel_number, freq & 0xff); - setregs (0xb0 + channel_number, (octave << 2) + 0x20 + (freq >> 8)); + } else { + setregs(0xa0 + channel_number, freq & 0xff); + setregs(0xb0 + channel_number, (octave << 2) + 0x20 + (freq >> 8)); c->lasttune = tunehigh; c->gototune = tunehigh + ((i->glide + 0x80) & 0xff) - 0x80; // set destination c->portspeed = i->portamento; } - if (!i->vibrato) + if(!i->vibrato) c->vibwait = c->vibspeed = c->vibrate = 0; - else - { + else { c->vibwait = i->vibdelay; // PASCAL: c->vibspeed = ((i->vibrato >> 4) & 15) + 1; c->vibspeed = (i->vibrato >> 4) + 2; c->vibrate = (i->vibrato & 15) + 1; } - if (!(c->trmstay & 0xf0)) - { + if(!(c->trmstay & 0xf0)) { c->trmwait = (i->tremwait & 0xf0) >> 3; // PASCAL: c->trmspeed = (i->mod_trem >> 4) & 15; c->trmspeed = i->mod_trem >> 4; @@ -782,8 +648,7 @@ CldsPlayer::playsound (int inst_number, int channel_number, int tunehigh) c->trmcount = 0; } - if (!(c->trmstay & 0x0f)) - { + if(!(c->trmstay & 0x0f)) { c->trcwait = (i->tremwait & 15) << 1; // PASCAL: c->trcspeed = (i->car_trem >> 4) & 15; c->trcspeed = i->car_trem >> 4; @@ -793,25 +658,21 @@ CldsPlayer::playsound (int inst_number, int channel_number, int tunehigh) c->arp_size = i->arpeggio & 15; c->arp_speed = i->arpeggio >> 4; - memcpy (c->arp_tab, i->arp_tab, 12); + memcpy(c->arp_tab, i->arp_tab, 12); c->keycount = i->keyoff; - c->nextvol = c->glideto = c->finetune = c->vibcount = c->arp_pos = - c->arp_count = 0; + c->nextvol = c->glideto = c->finetune = c->vibcount = c->arp_pos = c->arp_count = 0; } -inline void -CldsPlayer::setregs (unsigned char reg, unsigned char val) +inline void CldsPlayer::setregs(unsigned char reg, unsigned char val) { - if (fmchip[reg] == val) - return; + if(fmchip[reg] == val) return; fmchip[reg] = val; - opl->write (reg, val); + opl->write(reg, val); } -inline void -CldsPlayer::setregs_adv (unsigned char reg, unsigned char mask, - unsigned char val) +inline void CldsPlayer::setregs_adv(unsigned char reg, unsigned char mask, + unsigned char val) { - setregs (reg, (fmchip[reg] & mask) | val); + setregs(reg, (fmchip[reg] & mask) | val); } diff --git a/src/adplug/core/lds.h b/src/adplug/core/lds.h index 5e42129..97f06c1 100644 --- a/src/adplug/core/lds.h +++ b/src/adplug/core/lds.h @@ -29,7 +29,7 @@ class CldsPlayer: public CPlayer CldsPlayer(Copl *newopl); virtual ~CldsPlayer(); - bool load(VFSFile &fd, const CFileProvider &fp); + bool load(const std::string &filename, const CFileProvider &fp); virtual bool update(); virtual void rewind(int subsong = -1); float getrefresh() { return 70.0f; } @@ -43,49 +43,49 @@ class CldsPlayer: public CPlayer private: typedef struct { - unsigned char mod_misc, mod_vol, mod_ad, mod_sr, mod_wave, + unsigned char mod_misc, mod_vol, mod_ad, mod_sr, mod_wave, car_misc, car_vol, car_ad, car_sr, car_wave, feedback, keyoff, portamento, glide, finetune, vibrato, vibdelay, mod_trem, car_trem, tremwait, arpeggio, arp_tab[12]; - unsigned short start, size; - unsigned char fms; - unsigned short transp; - unsigned char midinst, midvelo, midkey, midtrans, middum1, middum2; + unsigned short start, size; + unsigned char fms; + unsigned short transp; + unsigned char midinst, midvelo, midkey, midtrans, middum1, middum2; } SoundBank; typedef struct { - unsigned short gototune, lasttune, packpos; - unsigned char finetune, glideto, portspeed, nextvol, volmod, volcar, + unsigned short gototune, lasttune, packpos; + unsigned char finetune, glideto, portspeed, nextvol, volmod, volcar, vibwait, vibspeed, vibrate, trmstay, trmwait, trmspeed, trmrate, trmcount, trcwait, trcspeed, trcrate, trccount, arp_size, arp_speed, keycount, vibcount, arp_pos, arp_count, packwait, arp_tab[12]; struct { - unsigned char chandelay, sound; - unsigned short high; + unsigned char chandelay, sound; + unsigned short high; } chancheat; } Channel; typedef struct { - unsigned short patnum; - unsigned char transpose; + unsigned short patnum; + unsigned char transpose; } Position; - static const unsigned short frequency[]; - static const unsigned char vibtab[], tremtab[]; - static const unsigned short maxsound, maxpos; + static const unsigned short frequency[]; + static const unsigned char vibtab[], tremtab[]; + static const unsigned short maxsound, maxpos; - SoundBank *soundbank; - Channel channel[9]; - Position *positions; - unsigned char fmchip[0xff], jumping, fadeonoff, allvolume, hardfade, + SoundBank *soundbank; + Channel channel[9]; + Position *positions; + unsigned char fmchip[0xff], jumping, fadeonoff, allvolume, hardfade, tempo_now, pattplay, tempo, regbd, chandelay[9], mode, pattlen; - unsigned short posplay, jumppos, *patterns, speed; - bool playing, songlooped; - unsigned int numpatch, numposi, mainvolume; + unsigned short posplay, jumppos, *patterns, speed; + bool playing, songlooped; + unsigned int numpatch, numposi, mainvolume; - void playsound(int inst_number, int channel_number, int tunehigh); - inline void setregs(unsigned char reg, unsigned char val); - inline void setregs_adv(unsigned char reg, unsigned char mask, - unsigned char val); + void playsound(int inst_number, int channel_number, int tunehigh); + inline void setregs(unsigned char reg, unsigned char val); + inline void setregs_adv(unsigned char reg, unsigned char mask, + unsigned char val); }; diff --git a/src/adplug/core/mad.cc b/src/adplug/core/mad.cc index f87b3b4..17d93e3 100644 --- a/src/adplug/core/mad.cc +++ b/src/adplug/core/mad.cc @@ -19,128 +19,109 @@ mad.cpp - MAD loader by Riven the Mage <riven@ok.ru> */ -#include <string.h> - +#include <cstring> #include "mad.h" /* -------- Public Methods -------------------------------- */ -CPlayer * -CmadLoader::factory (Copl * newopl) +CPlayer *CmadLoader::factory(Copl *newopl) { - return new CmadLoader (newopl); + return new CmadLoader(newopl); } -bool -CmadLoader::load (VFSFile & fd, const CFileProvider & fp) +bool CmadLoader::load(const std::string &filename, const CFileProvider &fp) { - binistream *f = fp.open (fd); - if (!f) - return false; - const unsigned char conv_inst[10] = { 2, 1, 10, 9, 4, 3, 6, 5, 8, 7 }; + binistream *f = fp.open(filename); if(!f) return false; + const unsigned char conv_inst[10] = { 2,1,10,9,4,3,6,5,8,7 }; unsigned int i, j, k, t = 0; // 'MAD+' - signed ? - char id[4]; - f->readString (id, 4); - if (strncmp (id, "MAD+", 4)) - { - fp.close (f); - return false; - } + char id[4]; f->readString(id, 4); + if (strncmp(id,"MAD+",4)) { fp.close(f); return false; } // load instruments - for (i = 0; i < 9; i++) - { - f->readString (instruments[i].name, 8); - for (j = 0; j < 12; j++) - instruments[i].data[j] = f->readInt (1); + for(i = 0; i < 9; i++) { + f->readString(instruments[i].name, 8); + for(j = 0; j < 12; j++) instruments[i].data[j] = f->readInt(1); } - f->ignore (1); + f->ignore(1); // data for Protracker - length = f->readInt (1); - nop = f->readInt (1); - timer = f->readInt (1); + length = f->readInt(1); nop = f->readInt(1); timer = f->readInt(1); // init CmodPlayer - realloc_instruments (9); - realloc_order (length); - realloc_patterns (nop, 32, 9); - init_trackord (); + realloc_instruments(9); + realloc_order(length); + realloc_patterns(nop,32,9); + init_trackord(); // load tracks - for (i = 0; i < nop; i++) - for (k = 0; k < 32; k++) - for (j = 0; j < 9; j++) - { + for(i = 0; i < nop; i++) + for(k = 0; k < 32; k++) + for(j = 0; j < 9; j++) { t = i * 9 + j; // read event - unsigned char event = f->readInt (1); + unsigned char event = f->readInt(1); // convert event if (event < 0x61) tracks[t][k].note = event; - if (event == 0xFF) // 0xFF: Release note + if (event == 0xFF) // 0xFF: Release note tracks[t][k].command = 8; - if (event == 0xFE) // 0xFE: Pattern Break + if (event == 0xFE) // 0xFE: Pattern Break tracks[t][k].command = 13; } // load order - for (i = 0; i < length; i++) - order[i] = f->readInt (1) - 1; + for(i = 0; i < length; i++) order[i] = f->readInt(1) - 1; - fp.close (f); + fp.close(f); // convert instruments - for (i = 0; i < 9; i++) - for (j = 0; j < 10; j++) + for(i = 0; i < 9; i++) + for(j = 0; j < 10; j++) inst[i].data[conv_inst[j]] = instruments[i].data[j]; // data for Protracker restartpos = 0; initspeed = 1; - rewind (0); + rewind(0); return true; } -void -CmadLoader::rewind (int subsong) +void CmadLoader::rewind(int subsong) { - CmodPlayer::rewind (subsong); + CmodPlayer::rewind(subsong); - // default instruments - for (int i = 0; i < 9; i++) - { - channel[i].inst = i; + // default instruments + for (int i=0;i<9;i++) + { + channel[i].inst = i; - channel[i].vol1 = 63 - (inst[i].data[10] & 63); - channel[i].vol2 = 63 - (inst[i].data[9] & 63); - } + channel[i].vol1 = 63 - (inst[i].data[10] & 63); + channel[i].vol2 = 63 - (inst[i].data[9] & 63); + } } -float -CmadLoader::getrefresh () +float CmadLoader::getrefresh() { - return (float) timer; + return (float)timer; } -std::string CmadLoader::gettype () +std::string CmadLoader::gettype() { - return std::string ("Mlat Adlib Tracker"); + return std::string("Mlat Adlib Tracker"); } -std::string CmadLoader::getinstrument (unsigned int n) +std::string CmadLoader::getinstrument(unsigned int n) { - return std::string (instruments[n].name, 8); + return std::string(instruments[n].name,8); } -unsigned int -CmadLoader::getinstruments () +unsigned int CmadLoader::getinstruments() { - return 9; + return 9; } diff --git a/src/adplug/core/mad.h b/src/adplug/core/mad.h index 7631de9..061685d 100644 --- a/src/adplug/core/mad.h +++ b/src/adplug/core/mad.h @@ -24,25 +24,25 @@ class CmadLoader: public CmodPlayer { public: - static CPlayer *factory(Copl *newopl); + static CPlayer *factory(Copl *newopl); - CmadLoader(Copl *newopl) : CmodPlayer(newopl) { }; + CmadLoader(Copl *newopl) : CmodPlayer(newopl) { }; - bool load(VFSFile &fd, const CFileProvider &fp); - void rewind(int subsong); - float getrefresh(); + bool load(const std::string &filename, const CFileProvider &fp); + void rewind(int subsong); + float getrefresh(); - std::string gettype(); - std::string getinstrument(unsigned int n); - unsigned int getinstruments(); + std::string gettype(); + std::string getinstrument(unsigned int n); + unsigned int getinstruments(); private: - struct mad_instrument - { - char name[8]; - unsigned char data[12]; // last two unused - } instruments[9]; + struct mad_instrument + { + char name[8]; + unsigned char data[12]; // last two unused + } instruments[9]; - unsigned char timer; + unsigned char timer; }; diff --git a/src/adplug/core/mid.cc b/src/adplug/core/mid.cc index 3f78c31..dc6c98d 100644 --- a/src/adplug/core/mid.cc +++ b/src/adplug/core/mid.cc @@ -1,6 +1,6 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. - * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al. + * Copyright (C) 1999 - 2008 Simon Peter, <dn.tlp@gmx.net>, et al. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,6 +25,9 @@ * .LAA - a raw save of a Lucas Arts Adlib music * or * a raw save of a LucasFilm Adlib music + * .MID - a "midi" save of a Lucas Arts Adlib music + * - or general MIDI files + * .CMF - Creative Music Format * .SCI - the sierra "midi" format. * Files must be in the form * xxxNAME.sci @@ -32,6 +35,38 @@ * xxxPATCH.003 (patch.003 must be saved from the * sierra resource from each game.) * + * 6/2/2000: v1.0 relased by phil hassey + * Status: LAA is almost perfect + * - some volumes are a bit off (intrument too quiet) + * MID is fine (who wants to listen to MIDI vid adlib anyway) + * CMF is okay (still needs the adlib rythm mode implemented + * for real) + * 6/6/2000: + * Status: SCI: there are two SCI formats, orginal and advanced. + * original: (Found in SCI/EGA Sierra Adventures) + * played almost perfectly, I believe + * there is one mistake in the instrument + * loader that causes some sounds to + * not be quite right. Most sounds are fine. + * advanced: (Found in SCI/VGA Sierra Adventures) + * These are multi-track files. (Thus the + * player had to be modified to work with + * them.) This works fine. + * There are also multiple tunes in each file. + * I think some of them are supposed to be + * played at the same time, but I'm not sure + * when. + * 8/16/2000: + * Status: LAA: now EGA and VGA lucas games work pretty well + * + * 10/15/2005: Changes by Simon Peter + * Added rhythm mode support for CMF format. + * + * 09/13/2008: Changes by Adam Nielsen (malvineous@shikadi.net) + * Fixed a couple of CMF rhythm mode bugs + * Disabled note velocity for CMF files + * Added support for nonstandard CMF AM+VIB controller (for VGFM CMFs) + * * Other acknowledgements: * Allegro - for the midi instruments and the midi volume table * SCUMM Revisited - for getting the .LAA / .MIDs out of those @@ -51,10 +86,9 @@ #ifdef TESTING #define midiprintf printf #else -void -CmidPlayer::midiprintf (const char *format, ...) -{ -} +void CmidPlayer::midiprintf(const char *format, ...) + { + } #endif #define LUCAS_STYLE 1 @@ -63,8 +97,8 @@ CmidPlayer::midiprintf (const char *format, ...) #define SIERRA_STYLE 8 // AdLib melodic and rhythm mode defines -#define ADLIB_MELODIC 0 -#define ADLIB_RYTHM 1 +#define ADLIB_MELODIC 0 +#define ADLIB_RYTHM 1 // File types #define FILE_LUCAS 1 @@ -75,1027 +109,1002 @@ CmidPlayer::midiprintf (const char *format, ...) #define FILE_OLDLUCAS 6 // AdLib standard operator table -const unsigned char -CmidPlayer::adlib_opadd[] = - { 0x00, 0x01, 0x02, 0x08, 0x09, 0x0A, 0x10, 0x11, 0x12 }; - -// dunno -const int -CmidPlayer::ops[] = - { 0x20, 0x20, 0x40, 0x40, 0x60, 0x60, 0x80, 0x80, 0xe0, 0xe0, 0xc0 }; +const unsigned char CmidPlayer::adlib_opadd[] = {0x00 ,0x01 ,0x02 ,0x08 ,0x09 ,0x0A ,0x10 ,0x11 ,0x12}; // map CMF drum channels 12 - 15 to corresponding AdLib drum operators // bass drum (channel 11) not mapped, cause it's handled like a normal instrument -const int -CmidPlayer::map_chan[] = { 0x14, 0x12, 0x15, 0x11 }; +const int CmidPlayer::map_chan[] = { 0x14, 0x12, 0x15, 0x11 }; // Standard AdLib frequency table -const int -CmidPlayer::fnums[] = - { 0x16b, 0x181, 0x198, 0x1b0, 0x1ca, 0x1e5, 0x202, 0x220, 0x241, 0x263, -0x287, 0x2ae }; +const int CmidPlayer::fnums[] = { 0x16b,0x181,0x198,0x1b0,0x1ca,0x1e5,0x202,0x220,0x241,0x263,0x287,0x2ae }; // Map CMF drum channels 11 - 15 to corresponding AdLib drum channels -const int -CmidPlayer::percussion_map[] = { 6, 7, 8, 8, 7 }; +const int CmidPlayer::percussion_map[] = { 6, 7, 8, 8, 7 }; -CPlayer * -CmidPlayer::factory (Copl * newopl) +CPlayer *CmidPlayer::factory(Copl *newopl) { - return new CmidPlayer (newopl); + return new CmidPlayer(newopl); } -CmidPlayer::CmidPlayer (Copl * newopl):CPlayer (newopl), author (&emptystr), title (&emptystr), remarks (&emptystr), -emptystr ('\0'), flen (0), data (0) +CmidPlayer::CmidPlayer(Copl *newopl) + : CPlayer(newopl), author(&emptystr), title(&emptystr), remarks(&emptystr), + emptystr('\0'), flen(0), data(0) { } -unsigned char -CmidPlayer::datalook (long pos) +unsigned char CmidPlayer::datalook(long pos) { - if (pos < 0 || pos >= flen) - return (0); - return (data[pos]); + if (pos<0 || pos >= flen) return(0); + return(data[pos]); } -unsigned long -CmidPlayer::getnexti (unsigned long num) +unsigned long CmidPlayer::getnexti(unsigned long num) { - unsigned long v = 0; - unsigned long i; - - for (i = 0; i < num; i++) - { - v += (datalook (pos) << (8 * i)); - pos++; - } - return (v); -} + unsigned long v=0; + unsigned long i; -unsigned long -CmidPlayer::getnext (unsigned long num) -{ - unsigned long v = 0; - unsigned long i; - - for (i = 0; i < num; i++) - { - v <<= 8; - v += datalook (pos); - pos++; - } - return (v); + for (i=0; i<num; i++) + { + v+=(datalook(pos)<<(8*i)); pos++; + } + return(v); } -unsigned long -CmidPlayer::getval () +unsigned long CmidPlayer::getnext(unsigned long num) { - int v = 0; - unsigned char b; - - b = (unsigned char) getnext (1); - v = b & 0x7f; - while ((b & 0x80) != 0) - { - b = (unsigned char) getnext (1); - v = (v << 7) + (b & 0x7F); - } - return (v); + unsigned long v=0; + unsigned long i; + + for (i=0; i<num; i++) + { + v<<=8; + v+=datalook(pos); pos++; + } + return(v); } -bool -CmidPlayer::load_sierra_ins (const std::string & fname, - const CFileProvider & fp) +unsigned long CmidPlayer::getval() { - long i, j, k, l; - unsigned char ins[28]; - char *pfilename; - binistream *f; - - pfilename = (char *) malloc (fname.length () + 9); - strcpy (pfilename, fname.c_str ()); - j = 0; - for (i = strlen (pfilename) - 1; i >= 0; i--) - if (pfilename[i] == '/' || pfilename[i] == '\\') - { - j = i + 1; - break; - } - sprintf (pfilename + j + 3, "patch.003"); - - VFSFile instfd (pfilename, "rb"); - f = fp.open (instfd); - free (pfilename); - if (!f) - return false; - - f->ignore (2); - stins = 0; - for (i = 0; i < 2; i++) - { - for (k = 0; k < 48; k++) - { - l = i * 48 + k; - midiprintf ("\n%2ld: ", l); - for (j = 0; j < 28; j++) - ins[j] = f->readInt (1); + int v=0; + unsigned char b; - myinsbank[l][0] = (ins[9] * 0x80) + (ins[10] * 0x40) + (ins[5] * 0x20) + (ins[11] * 0x10) + ins[1]; //1=ins5 - myinsbank[l][1] = (ins[22] * 0x80) + (ins[23] * 0x40) + (ins[18] * 0x20) + (ins[24] * 0x10) + ins[14]; //1=ins18 - - myinsbank[l][2] = (ins[0] << 6) + ins[8]; - myinsbank[l][3] = (ins[13] << 6) + ins[21]; - - myinsbank[l][4] = (ins[3] << 4) + ins[6]; - myinsbank[l][5] = (ins[16] << 4) + ins[19]; - myinsbank[l][6] = (ins[4] << 4) + ins[7]; - myinsbank[l][7] = (ins[17] << 4) + ins[20]; + b=(unsigned char)getnext(1); + v=b&0x7f; + while ((b&0x80) !=0) + { + b=(unsigned char)getnext(1); + v = (v << 7) + (b & 0x7F); + } + return(v); +} - myinsbank[l][8] = ins[26]; - myinsbank[l][9] = ins[27]; +bool CmidPlayer::load_sierra_ins(const std::string &fname, const CFileProvider &fp) +{ + long i,j,k,l; + unsigned char ins[28]; + char *pfilename; + binistream *f; + + pfilename = (char *)malloc(fname.length()+9); + strcpy(pfilename,fname.c_str()); + j=0; + for(i=strlen(pfilename)-1; i >= 0; i--) + if(pfilename[i] == '/' || pfilename[i] == '\\') { + j = i+1; + break; + } + sprintf(pfilename+j+3,"patch.003"); - myinsbank[l][10] = ((ins[2] << 1)) + (1 - (ins[12] & 1)); - //(ins[12] ? 0:1)+((ins[2]<<1)); + f = fp.open(pfilename); + free(pfilename); + if(!f) return false; - for (j = 0; j < 11; j++) - midiprintf ("%02X ", myinsbank[l][j]); - stins++; - } - f->ignore (2); - } + f->ignore(2); + stins = 0; + for (i=0; i<2; i++) + { + for (k=0; k<48; k++) + { + l=i*48+k; + midiprintf ("\n%2ld: ",l); + for (j=0; j<28; j++) + ins[j] = f->readInt(1); + + myinsbank[l][0]= + (ins[9]*0x80) + (ins[10]*0x40) + + (ins[5]*0x20) + (ins[11]*0x10) + + ins[1]; //1=ins5 + myinsbank[l][1]= + (ins[22]*0x80) + (ins[23]*0x40) + + (ins[18]*0x20) + (ins[24]*0x10) + + ins[14]; //1=ins18 + + myinsbank[l][2]=(ins[0]<<6)+ins[8]; + myinsbank[l][3]=(ins[13]<<6)+ins[21]; + + myinsbank[l][4]=(ins[3]<<4)+ins[6]; + myinsbank[l][5]=(ins[16]<<4)+ins[19]; + myinsbank[l][6]=(ins[4]<<4)+ins[7]; + myinsbank[l][7]=(ins[17]<<4)+ins[20]; + + myinsbank[l][8]=ins[26]; + myinsbank[l][9]=ins[27]; + + myinsbank[l][10]=((ins[2]<<1))+(1-(ins[12]&1)); + //(ins[12] ? 0:1)+((ins[2]<<1)); + + for (j=0; j<11; j++) + midiprintf ("%02X ",myinsbank[l][j]); + stins++; + } + f->ignore(2); + } - fp.close (f); - memcpy (smyinsbank, myinsbank, 128 * 16); - return true; + fp.close(f); + memcpy(smyinsbank, myinsbank, 128 * 16); + return true; } -void -CmidPlayer::sierra_next_section () +void CmidPlayer::sierra_next_section() { - int i, j; - - for (i = 0; i < 16; i++) - track[i].on = 0; - - midiprintf ("\n\nnext adv sierra section:\n"); - - pos = sierra_pos; - i = 0; - j = 0; - while (i != 0xff) - { - getnext (1); - curtrack = j; - j++; - track[curtrack].on = 1; - track[curtrack].spos = getnext (1); - track[curtrack].spos += (getnext (1) << 8) + 4; //4 best usually +3? not 0,1,2 or 5 -// track[curtrack].spos=getnext(1)+(getnext(1)<<8)+4; // dynamite!: doesn't optimize correctly!! - track[curtrack].tend = flen; //0xFC will kill it - track[curtrack].iwait = 0; - track[curtrack].pv = 0; - midiprintf ("track %u starts at %lx\n", curtrack, track[curtrack].spos); - - getnext (2); - i = getnext (1); - } - getnext (2); - deltas = 0x20; - sierra_pos = pos; - //getch(); - - fwait = 0; - doing = 1; + int i,j; + + for (i=0; i<16; i++) + track[i].on=0; + + midiprintf("\n\nnext adv sierra section:\n"); + + pos=sierra_pos; + i=0;j=0; + while (i!=0xff) + { + getnext(1); + curtrack=j; j++; + track[curtrack].on=1; + track[curtrack].spos = getnext(1); + track[curtrack].spos += (getnext(1) << 8) + 4; //4 best usually +3? not 0,1,2 or 5 +// track[curtrack].spos=getnext(1)+(getnext(1)<<8)+4; // dynamite!: doesn't optimize correctly!! + track[curtrack].tend=flen; //0xFC will kill it + track[curtrack].iwait=0; + track[curtrack].pv=0; + midiprintf ("track %u starts at %lx\n",curtrack,track[curtrack].spos); + + getnext(2); + i=getnext(1); + } + getnext(2); + deltas=0x20; + sierra_pos=pos; + //getch(); + + fwait=0; + doing=1; } -bool -CmidPlayer::load (VFSFile & fd, const CFileProvider & fp) +bool CmidPlayer::load(const std::string &filename, const CFileProvider &fp) { - binistream *f = fp.open (fd); - if (!f) - return false; - int good; - unsigned char s[6]; - std::string filename (fd.filename ()); - - f->readString ((char *) s, 6); - good = 0; - subsongs = 0; - switch (s[0]) - { - case 'A': - if (s[1] == 'D' && s[2] == 'L') - good = FILE_LUCAS; - break; - case 0x84: - if (s[1] == 0x00 && load_sierra_ins (filename, fp)) - { - if (s[2] == 0xf0) - good = FILE_ADVSIERRA; - else - good = FILE_SIERRA; - break; + binistream *f = fp.open(filename); if(!f) return false; + int good; + unsigned char s[6]; + + f->readString((char *)s, 6); + good=0; + subsongs=0; + switch(s[0]) + { + case 'A': + if (s[1]=='D' && s[2]=='L') good=FILE_LUCAS; + break; + case 'M': + if (s[1]=='T' && s[2]=='h' && s[3]=='d') good=FILE_MIDI; + break; + case 'C': + if (s[1]=='T' && s[2]=='M' && s[3]=='F') good=FILE_CMF; + break; + case 0x84: + if (s[1]==0x00 && load_sierra_ins(filename, fp)) { + if (s[2]==0xf0) + good=FILE_ADVSIERRA; + else + good=FILE_SIERRA; + } + break; + default: + if (s[4]=='A' && s[5]=='D') good=FILE_OLDLUCAS; + break; + } + + if (good!=0) + subsongs=1; + else { + fp.close(f); + return false; } - default: - if (s[4] == 'A' && s[5] == 'D') - good = FILE_OLDLUCAS; - break; - } - - if (good != 0) - subsongs = 1; - else - { - fp.close (f); - return false; - } - - type = good; - f->seek (0); - flen = fp.filesize (f); - data = new unsigned char[flen]; - f->readString ((char *) data, flen); - - fp.close (f); - rewind (0); - return true; + + type=good; + f->seek(0); + flen = fp.filesize(f); + data = new unsigned char [flen]; + f->readString((char *)data, flen); + + fp.close(f); + rewind(0); + return true; } -void -CmidPlayer::midi_write_adlib (unsigned int r, unsigned char v) +void CmidPlayer::midi_write_adlib(unsigned int r, unsigned char v) { - opl->write (r, v); - adlib_data[r] = v; + opl->write(r,v); + adlib_data[r]=v; } -void -CmidPlayer::midi_fm_instrument (int voice, unsigned char *inst) +void CmidPlayer::midi_fm_instrument(int voice, unsigned char *inst) { - if ((adlib_style & SIERRA_STYLE) != 0) - midi_write_adlib (0xbd, 0); //just gotta make sure this happens.. - //'cause who knows when it'll be - //reset otherwise. - - - midi_write_adlib (0x20 + adlib_opadd[voice], inst[0]); - midi_write_adlib (0x23 + adlib_opadd[voice], inst[1]); - - if ((adlib_style & LUCAS_STYLE) != 0) - { - midi_write_adlib (0x43 + adlib_opadd[voice], 0x3f); - if ((inst[10] & 1) == 0) - midi_write_adlib (0x40 + adlib_opadd[voice], inst[2]); - else - midi_write_adlib (0x40 + adlib_opadd[voice], 0x3f); - } - else - { - if ((adlib_style & SIERRA_STYLE) != 0) - { - midi_write_adlib (0x40 + adlib_opadd[voice], inst[2]); - midi_write_adlib (0x43 + adlib_opadd[voice], inst[3]); - } - else - { - midi_write_adlib (0x40 + adlib_opadd[voice], inst[2]); - if ((inst[10] & 1) == 0) - midi_write_adlib (0x43 + adlib_opadd[voice], inst[3]); - else - midi_write_adlib (0x43 + adlib_opadd[voice], 0); + if ((adlib_style&SIERRA_STYLE)!=0) + midi_write_adlib(0xbd,0); //just gotta make sure this happens.. + //'cause who knows when it'll be + //reset otherwise. + + + midi_write_adlib(0x20+adlib_opadd[voice],inst[0]); + midi_write_adlib(0x23+adlib_opadd[voice],inst[1]); + + if (adlib_style & LUCAS_STYLE) { + midi_write_adlib(0x43+adlib_opadd[voice],0x3f); + if ((inst[10] & 1)==0) + midi_write_adlib(0x40+adlib_opadd[voice],inst[2]); + else + midi_write_adlib(0x40+adlib_opadd[voice],0x3f); + + } else if ((adlib_style & SIERRA_STYLE) || (adlib_style & CMF_STYLE)) { + midi_write_adlib(0x40+adlib_opadd[voice],inst[2]); + midi_write_adlib(0x43+adlib_opadd[voice],inst[3]); + + } else { + midi_write_adlib(0x40+adlib_opadd[voice],inst[2]); + if ((inst[10] & 1)==0) + midi_write_adlib(0x43+adlib_opadd[voice],inst[3]); + else + midi_write_adlib(0x43+adlib_opadd[voice],0); } - } - midi_write_adlib (0x60 + adlib_opadd[voice], inst[4]); - midi_write_adlib (0x63 + adlib_opadd[voice], inst[5]); - midi_write_adlib (0x80 + adlib_opadd[voice], inst[6]); - midi_write_adlib (0x83 + adlib_opadd[voice], inst[7]); - midi_write_adlib (0xe0 + adlib_opadd[voice], inst[8]); - midi_write_adlib (0xe3 + adlib_opadd[voice], inst[9]); + midi_write_adlib(0x60+adlib_opadd[voice],inst[4]); + midi_write_adlib(0x63+adlib_opadd[voice],inst[5]); + midi_write_adlib(0x80+adlib_opadd[voice],inst[6]); + midi_write_adlib(0x83+adlib_opadd[voice],inst[7]); + midi_write_adlib(0xe0+adlib_opadd[voice],inst[8]); + midi_write_adlib(0xe3+adlib_opadd[voice],inst[9]); - midi_write_adlib (0xc0 + voice, inst[10]); + midi_write_adlib(0xc0+voice,inst[10]); } -void -CmidPlayer::midi_fm_percussion (int ch, unsigned char *inst) +void CmidPlayer::midi_fm_percussion(int ch, unsigned char *inst) { - int opadd = map_chan[ch - 12]; - - midi_write_adlib (0x20 + opadd, inst[0]); - midi_write_adlib (0x40 + opadd, inst[2]); - midi_write_adlib (0x60 + opadd, inst[4]); - midi_write_adlib (0x80 + opadd, inst[6]); - midi_write_adlib (0xe0 + opadd, inst[8]); - midi_write_adlib (0xc0 + opadd, inst[10]); + int opadd = map_chan[ch - 12]; + + midi_write_adlib(0x20 + opadd, inst[0]); + midi_write_adlib(0x40 + opadd, inst[2]); + midi_write_adlib(0x60 + opadd, inst[4]); + midi_write_adlib(0x80 + opadd, inst[6]); + midi_write_adlib(0xe0 + opadd, inst[8]); + if (opadd < 0x13) // only output this for the modulator, not the carrier, as it affects the entire channel + midi_write_adlib(0xc0 + percussion_map[ch - 11], inst[10]); } -void -CmidPlayer::midi_fm_volume (int voice, int volume) +void CmidPlayer::midi_fm_volume(int voice, int volume) { - int vol; + int vol; - if ((adlib_style & SIERRA_STYLE) == 0) //sierra likes it loud! - { - vol = volume >> 2; - - if ((adlib_style & LUCAS_STYLE) != 0) - { - if ((adlib_data[0xc0 + voice] & 1) == 1) - midi_write_adlib (0x40 + adlib_opadd[voice], - (unsigned char) ((63 - vol) | - (adlib_data - [0x40 + - adlib_opadd[voice]] & 0xc0))); - midi_write_adlib (0x43 + adlib_opadd[voice], - (unsigned char) ((63 - vol) | - (adlib_data - [0x43 + - adlib_opadd[voice]] & 0xc0))); - } - else + if ((adlib_style&SIERRA_STYLE)==0) //sierra likes it loud! { - if ((adlib_data[0xc0 + voice] & 1) == 1) - midi_write_adlib (0x40 + adlib_opadd[voice], - (unsigned char) ((63 - vol) | - (adlib_data - [0x40 + - adlib_opadd[voice]] & 0xc0))); - midi_write_adlib (0x43 + adlib_opadd[voice], - (unsigned char) ((63 - vol) | - (adlib_data - [0x43 + - adlib_opadd[voice]] & 0xc0))); + vol=volume>>2; + + if ((adlib_style&LUCAS_STYLE)!=0) + { + if ((adlib_data[0xc0+voice]&1)==1) + midi_write_adlib(0x40+adlib_opadd[voice], (unsigned char)((63-vol) | + (adlib_data[0x40+adlib_opadd[voice]]&0xc0))); + midi_write_adlib(0x43+adlib_opadd[voice], (unsigned char)((63-vol) | + (adlib_data[0x43+adlib_opadd[voice]]&0xc0))); + } + else + { + if ((adlib_data[0xc0+voice]&1)==1) + midi_write_adlib(0x40+adlib_opadd[voice], (unsigned char)((63-vol) | + (adlib_data[0x40+adlib_opadd[voice]]&0xc0))); + midi_write_adlib(0x43+adlib_opadd[voice], (unsigned char)((63-vol) | + (adlib_data[0x43+adlib_opadd[voice]]&0xc0))); + } } - } } -void -CmidPlayer::midi_fm_playnote (int voice, int note, int volume) +void CmidPlayer::midi_fm_playnote(int voice, int note, int volume) { - int freq = fnums[note % 12]; - int oct = note / 12; - int c; + int freq=fnums[note%12]; + int oct=note/12; + int c; - midi_fm_volume (voice, volume); - midi_write_adlib (0xa0 + voice, (unsigned char) (freq & 0xff)); + midi_fm_volume(voice,volume); + midi_write_adlib(0xa0+voice,(unsigned char)(freq&0xff)); - c = ((freq & 0x300) >> 8) + (oct << 2) + (adlib_mode == ADLIB_MELODIC - || voice < 6 ? (1 << 5) : 0); - midi_write_adlib (0xb0 + voice, (unsigned char) c); + c=((freq&0x300) >> 8)+((oct&7)<<2) + (adlib_mode == ADLIB_MELODIC || voice < 6 ? (1<<5) : 0); + midi_write_adlib(0xb0+voice,(unsigned char)c); } -void -CmidPlayer::midi_fm_endnote (int voice) +void CmidPlayer::midi_fm_endnote(int voice) { - //midi_fm_volume(voice,0); - //midi_write_adlib(0xb0+voice,0); + //midi_fm_volume(voice,0); + //midi_write_adlib(0xb0+voice,0); - midi_write_adlib (0xb0 + voice, - (unsigned char) (adlib_data[0xb0 + voice] & (255 - 32))); + midi_write_adlib(0xb0+voice,(unsigned char)(adlib_data[0xb0+voice]&(255-32))); } -void -CmidPlayer::midi_fm_reset () +void CmidPlayer::midi_fm_reset() { - int i; + int i; - opl->init (); + opl->init(); - for (i = 0; i < 256; i++) - midi_write_adlib (i, 0); + for (i=0; i<256; i++) + midi_write_adlib(i,0); - midi_write_adlib (0x01, 0x20); - midi_write_adlib (0xBD, 0xc0); + midi_write_adlib(0x01, 0x20); + midi_write_adlib(0xBD,0xc0); } -bool -CmidPlayer::update () +bool CmidPlayer::update() { - long w, v, note, vel, ctrl, nv, x, l, lnum; - int i = 0, j, c; - int on, onl, numchan; - int ret; - - if (doing == 1) - { - // just get the first wait and ignore it :> - for (curtrack = 0; curtrack < 16; curtrack++) - if (track[curtrack].on) - { - pos = track[curtrack].pos; - if (type != FILE_SIERRA && type != FILE_ADVSIERRA) - track[curtrack].iwait += getval (); - else - track[curtrack].iwait += getnext (1); - track[curtrack].pos = pos; - } - doing = 0; - } + long w,v,note,vel,ctrl,nv,x,l,lnum; + int i=0,j,c; + int on,onl,numchan; + int ret; - iwait = 0; - ret = 1; - - while (iwait == 0 && ret == 1) - { - for (curtrack = 0; curtrack < 16; curtrack++) - if (track[curtrack].on && track[curtrack].iwait == 0 && - track[curtrack].pos < track[curtrack].tend) - { - pos = track[curtrack].pos; - - v = getnext (1); - - // This is to do implied MIDI events. - if (v < 0x80) + if (doing == 1) { - v = track[curtrack].pv; - pos--; - } - track[curtrack].pv = (unsigned char) v; - - c = v & 0x0f; - midiprintf ("[%2lX]", v); - switch (v & 0xf0) - { - case 0x80: /*note off */ - note = getnext (1); - vel = getnext (1); - for (i = 0; i < 9; i++) - if (chp[i][0] == c && chp[i][1] == note) - { - midi_fm_endnote (i); - chp[i][0] = -1; - } - break; - case 0x90: /*note on */ - // doing=0; - note = getnext (1); - vel = getnext (1); - - if (adlib_mode == ADLIB_RYTHM) - numchan = 6; - else - numchan = 9; - - if (ch[c].on != 0) - { - for (i = 0; i < 18; i++) - chp[i][2]++; - - if (c < 11 || adlib_mode == ADLIB_MELODIC) - { - j = 0; - on = -1; - onl = 0; - for (i = 0; i < numchan; i++) - if (chp[i][0] == -1 && chp[i][2] > onl) + // just get the first wait and ignore it :> + for (curtrack=0; curtrack<16; curtrack++) + if (track[curtrack].on) { - onl = chp[i][2]; - on = i; - j = 1; + pos=track[curtrack].pos; + if (type != FILE_SIERRA && type !=FILE_ADVSIERRA) + track[curtrack].iwait+=getval(); + else + track[curtrack].iwait+=getnext(1); + track[curtrack].pos=pos; } + doing=0; + } - if (on == -1) - { - onl = 0; - for (i = 0; i < numchan; i++) - if (chp[i][2] > onl) - { - onl = chp[i][2]; - on = i; - } - } + iwait=0; + ret=1; - if (j == 0) - midi_fm_endnote (on); - } - else - on = percussion_map[c - 11]; + while (iwait==0 && ret==1) + { + for (curtrack=0; curtrack<16; curtrack++) + if (track[curtrack].on && track[curtrack].iwait==0 && + track[curtrack].pos < track[curtrack].tend) + { + pos=track[curtrack].pos; - if (vel != 0 && ch[c].inum >= 0 && ch[c].inum < 128) - { - if (adlib_mode == ADLIB_MELODIC || c < 12) - midi_fm_instrument (on, ch[c].ins); - else - midi_fm_percussion (c, ch[c].ins); - - if ((adlib_style & MIDI_STYLE) != 0) - { - nv = ((ch[c].vol * vel) / 128); - if ((adlib_style & LUCAS_STYLE) != 0) - nv *= 2; - if (nv > 127) - nv = 127; - nv = my_midi_fm_vol_table[nv]; - if ((adlib_style & LUCAS_STYLE) != 0) - nv = (int) ((float) sqrt ((float) nv) * 11); - } - else - { - nv = vel; - } - - midi_fm_playnote (on, note + ch[c].nshift, nv * 2); - chp[on][0] = c; - chp[on][1] = note; - chp[on][2] = 0; - - if (adlib_mode == ADLIB_RYTHM && c >= 11) - { - midi_write_adlib (0xbd, - adlib_data[0xbd] & ~(0x10 >> (c - 11))); - midi_write_adlib (0xbd, - adlib_data[0xbd] | (0x10 >> (c - 11))); - } + v=getnext(1); - } - else + // This is to do implied MIDI events. + if (v<0x80) {v=track[curtrack].pv; pos--;} + track[curtrack].pv=(unsigned char)v; + + c=v&0x0f; + midiprintf ("[%2lX]",v); + switch(v&0xf0) { - if (vel == 0) //same code as end note - { - for (i = 0; i < 9; i++) - if (chp[i][0] == c && chp[i][1] == note) - { - // midi_fm_volume(i,0); // really end the note - midi_fm_endnote (i); - chp[i][0] = -1; + case 0x80: /*note off*/ + note=getnext(1); vel=getnext(1); + for (i=0; i<9; i++) + if (chp[i][0]==c && chp[i][1]==note) + { + midi_fm_endnote(i); + chp[i][0]=-1; + } + break; + case 0x90: /*note on*/ + // doing=0; + note=getnext(1); vel=getnext(1); + + if(adlib_mode == ADLIB_RYTHM) + numchan = 6; + else + numchan = 9; + + if (ch[c].on!=0) + { + for (i=0; i<18; i++) + chp[i][2]++; + + if(c < 11 || adlib_mode == ADLIB_MELODIC) { + j=0; + on=-1;onl=0; + for (i=0; i<numchan; i++) + if (chp[i][0]==-1 && chp[i][2]>onl) + { onl=chp[i][2]; on=i; j=1; } + + if (on==-1) + { + onl=0; + for (i=0; i<numchan; i++) + if (chp[i][2]>onl) + { onl=chp[i][2]; on=i; } + } + + if (j==0) + midi_fm_endnote(on); + } else + on = percussion_map[c - 11]; + + if (vel!=0 && ch[c].inum>=0 && ch[c].inum<128) { + if (adlib_mode == ADLIB_MELODIC || c < 12) // 11 == bass drum, handled like a normal instrument, on == channel 6 thanks to percussion_map[] above + midi_fm_instrument(on,ch[c].ins); + else + midi_fm_percussion(c, ch[c].ins); + + if (adlib_style & MIDI_STYLE) { + nv=((ch[c].vol*vel)/128); + if ((adlib_style&LUCAS_STYLE)!=0) nv*=2; + if (nv>127) nv=127; + nv=my_midi_fm_vol_table[nv]; + if ((adlib_style&LUCAS_STYLE)!=0) + nv=(int)((float)sqrt((float)nv)*11); + } else if (adlib_style & CMF_STYLE) { + // CMF doesn't support note velocity (even though some files have them!) + nv = 127; + } else { + nv=vel; + } + + midi_fm_playnote(on,note+ch[c].nshift,nv*2); // sets freq in rhythm mode + chp[on][0]=c; + chp[on][1]=note; + chp[on][2]=0; + + if(adlib_mode == ADLIB_RYTHM && c >= 11) { + // Still need to turn off the perc instrument before playing it again, + // as not all songs send a noteoff. + midi_write_adlib(0xbd, adlib_data[0xbd] & ~(0x10 >> (c - 11))); + // Play the perc instrument + midi_write_adlib(0xbd, adlib_data[0xbd] | (0x10 >> (c - 11))); + } + + } else { + if (vel==0) { //same code as end note + if (adlib_mode == ADLIB_RYTHM && c >= 11) { + // Turn off the percussion instrument + midi_write_adlib(0xbd, adlib_data[0xbd] & ~(0x10 >> (c - 11))); + //midi_fm_endnote(percussion_map[c]); + chp[percussion_map[c - 11]][0]=-1; + } else { + for (i=0; i<9; i++) { + if (chp[i][0]==c && chp[i][1]==note) { + // midi_fm_volume(i,0); // really end the note + midi_fm_endnote(i); + chp[i][0]=-1; + } + } + } + } else { + // i forget what this is for. + chp[on][0]=-1; + chp[on][2]=0; + } } - } - else - { // i forget what this is for. - chp[on][0] = -1; - chp[on][2] = 0; - } - } - midiprintf (" [%d:%d:%ld:%ld]\n", c, ch[c].inum, note, vel); - } - else - midiprintf ("off"); - break; - case 0xa0: /*key after touch */ - note = getnext (1); - vel = getnext (1); - /* //this might all be good - for (i=0; i<9; i++) - if (chp[i][0]==c & chp[i][1]==note) - - midi_fm_playnote(i,note+cnote[c],my_midi_fm_vol_table[(cvols[c]*vel)/128]*2); - */ - break; - case 0xb0: /*control change .. pitch bend? */ - ctrl = getnext (1); - vel = getnext (1); - - switch (ctrl) - { - case 0x07: - midiprintf ("(pb:%d: %ld %ld)", c, ctrl, vel); - ch[c].vol = vel; - midiprintf ("vol"); - break; - case 0x67: - midiprintf ("\n\nhere:%ld\n\n", vel); - if ((adlib_style & CMF_STYLE) != 0) - { - adlib_mode = vel; - if (adlib_mode == ADLIB_RYTHM) - midi_write_adlib (0xbd, adlib_data[0xbd] | (1 << 5)); - else - midi_write_adlib (0xbd, adlib_data[0xbd] & ~(1 << 5)); - } - break; - } - break; - case 0xc0: /*patch change */ - x = getnext (1); - ch[c].inum = x; - for (j = 0; j < 11; j++) - ch[c].ins[j] = myinsbank[ch[c].inum][j]; - break; - case 0xd0: /*chanel touch */ - x = getnext (1); - break; - case 0xe0: /*pitch wheel */ - x = getnext (1); - x = getnext (1); - break; - case 0xf0: - switch (v) - { - case 0xf0: - case 0xf7: /*sysex */ - l = getval (); - if (datalook (pos + l) == 0xf7) - i = 1; - midiprintf ("{%ld}", l); - midiprintf ("\n"); - - if (datalook (pos) == 0x7d && - datalook (pos + 1) == 0x10 && datalook (pos + 2) < 16) - { - adlib_style = LUCAS_STYLE | MIDI_STYLE; - for (i = 0; i < l; i++) - { - midiprintf ("%x ", datalook (pos + i)); - if ((i - 3) % 10 == 0) - midiprintf ("\n"); - } - midiprintf ("\n"); - getnext (1); - getnext (1); - c = getnext (1); - getnext (1); - - // getnext(22); //temp - ch[c].ins[0] = - (unsigned char) ((getnext (1) << 4) + getnext (1)); - ch[c].ins[2] = - (unsigned char) (0xff - - (((getnext (1) << 4) + getnext (1)) & 0x3f)); - ch[c].ins[4] = - (unsigned char) (0xff - ((getnext (1) << 4) + getnext (1))); - ch[c].ins[6] = - (unsigned char) (0xff - ((getnext (1) << 4) + getnext (1))); - ch[c].ins[8] = - (unsigned char) ((getnext (1) << 4) + getnext (1)); - - ch[c].ins[1] = - (unsigned char) ((getnext (1) << 4) + getnext (1)); - ch[c].ins[3] = - (unsigned char) (0xff - - (((getnext (1) << 4) + getnext (1)) & 0x3f)); - ch[c].ins[5] = - (unsigned char) (0xff - ((getnext (1) << 4) + getnext (1))); - ch[c].ins[7] = - (unsigned char) (0xff - ((getnext (1) << 4) + getnext (1))); - ch[c].ins[9] = - (unsigned char) ((getnext (1) << 4) + getnext (1)); - - i = (getnext (1) << 4) + getnext (1); - ch[c].ins[10] = i; - - //if ((i&1)==1) ch[c].ins[10]=1; - - midiprintf ("\n%d: ", c); - for (i = 0; i < 11; i++) - midiprintf ("%2X ", ch[c].ins[i]); - getnext (l - 26); - } - else - { - midiprintf ("\n"); - for (j = 0; j < l; j++) - midiprintf ("%2lX ", getnext (1)); + midiprintf(" [%d:%d:%ld:%ld]\n",c,ch[c].inum,note,vel); + } + else + midiprintf ("off"); + break; + case 0xa0: /*key after touch */ + note=getnext(1); vel=getnext(1); + /* //this might all be good + for (i=0; i<9; i++) + if (chp[i][0]==c & chp[i][1]==note) + +midi_fm_playnote(i,note+cnote[c],my_midi_fm_vol_table[(cvols[c]*vel)/128]*2); + */ + break; + case 0xb0: /*control change .. pitch bend? */ + ctrl=getnext(1); vel=getnext(1); + + switch(ctrl) + { + case 0x07: + midiprintf ("(pb:%d: %ld %ld)",c,ctrl,vel); + ch[c].vol=vel; + midiprintf("vol"); + break; + case 0x63: + if (adlib_style & CMF_STYLE) { + // Custom extension to allow CMF files to switch the + // AM+VIB depth on and off (officially this is on, + // and there's no way to switch it off.) Controller + // values: + // 0 == AM+VIB off + // 1 == VIB on + // 2 == AM on + // 3 == AM+VIB on + midi_write_adlib(0xbd, (adlib_data[0xbd] & ~0xC0) | (vel << 6)); + midiprintf(" AM+VIB depth change - AM %s, VIB %s\n", + (adlib_data[0xbd] & 0x80) ? "on" : "off", + (adlib_data[0xbd] & 0x40) ? "on" : "off" + ); + } + break; + case 0x67: + midiprintf("Rhythm mode: %ld\n", vel); + if ((adlib_style&CMF_STYLE)!=0) { + adlib_mode=vel; + if(adlib_mode == ADLIB_RYTHM) + midi_write_adlib(0xbd, adlib_data[0xbd] | (1 << 5)); + else + midi_write_adlib(0xbd, adlib_data[0xbd] & ~(1 << 5)); + } + break; + } + break; + case 0xc0: /*patch change*/ + x=getnext(1); + ch[c].inum=x; + for (j=0; j<11; j++) + ch[c].ins[j]=myinsbank[ch[c].inum][j]; + break; + case 0xd0: /*chanel touch*/ + x=getnext(1); + break; + case 0xe0: /*pitch wheel*/ + x=getnext(1); + x=getnext(1); + break; + case 0xf0: + switch(v) + { + case 0xf0: + case 0xf7: /*sysex*/ + l=getval(); + if (datalook(pos+l)==0xf7) + i=1; + midiprintf("{%ld}",l); + midiprintf("\n"); + + if (datalook(pos)==0x7d && + datalook(pos+1)==0x10 && + datalook(pos+2)<16) + { + adlib_style=LUCAS_STYLE|MIDI_STYLE; + for (i=0; i<l; i++) + { + midiprintf ("%x ",datalook(pos+i)); + if ((i-3)%10 == 0) midiprintf("\n"); + } + midiprintf ("\n"); + getnext(1); + getnext(1); + c=getnext(1); + getnext(1); + + // getnext(22); //temp + ch[c].ins[0]=(unsigned char)((getnext(1)<<4)+getnext(1)); + ch[c].ins[2]=(unsigned char)(0xff-(((getnext(1)<<4)+getnext(1))&0x3f)); + ch[c].ins[4]=(unsigned char)(0xff-((getnext(1)<<4)+getnext(1))); + ch[c].ins[6]=(unsigned char)(0xff-((getnext(1)<<4)+getnext(1))); + ch[c].ins[8]=(unsigned char)((getnext(1)<<4)+getnext(1)); + + ch[c].ins[1]=(unsigned char)((getnext(1)<<4)+getnext(1)); + ch[c].ins[3]=(unsigned char)(0xff-(((getnext(1)<<4)+getnext(1))&0x3f)); + ch[c].ins[5]=(unsigned char)(0xff-((getnext(1)<<4)+getnext(1))); + ch[c].ins[7]=(unsigned char)(0xff-((getnext(1)<<4)+getnext(1))); + ch[c].ins[9]=(unsigned char)((getnext(1)<<4)+getnext(1)); + + i=(getnext(1)<<4)+getnext(1); + ch[c].ins[10]=i; + + //if ((i&1)==1) ch[c].ins[10]=1; + + midiprintf ("\n%d: ",c); + for (i=0; i<11; i++) + midiprintf ("%2X ",ch[c].ins[i]); + getnext(l-26); + } + else + { + midiprintf("\n"); + for (j=0; j<l; j++) + midiprintf ("%2lX ",getnext(1)); + } + + midiprintf("\n"); + if(i==1) + getnext(1); + break; + case 0xf1: + break; + case 0xf2: + getnext(2); + break; + case 0xf3: + getnext(1); + break; + case 0xf4: + break; + case 0xf5: + break; + case 0xf6: /*something*/ + case 0xf8: + case 0xfa: + case 0xfb: + case 0xfc: + //this ends the track for sierra. + if (type == FILE_SIERRA || + type == FILE_ADVSIERRA) + { + track[curtrack].tend=pos; + midiprintf ("endmark: %lu -- %lx\n",pos,pos); + } + break; + case 0xfe: + break; + case 0xfd: + break; + case 0xff: + v=getnext(1); + l=getval(); + midiprintf ("\n"); + midiprintf("{%lX_%lX}",v,l); + if (v==0x51) + { + lnum=getnext(l); + msqtr=lnum; /*set tempo*/ + midiprintf ("(qtr=%ld)",msqtr); + } + else + { + for (i=0; i<l; i++) + midiprintf ("%2lX ",getnext(1)); + } + break; + } + break; + default: midiprintf("%lX!",v); /* if we get down here, a error occurred */ + break; } - midiprintf ("\n"); - if (i == 1) - getnext (1); - break; - case 0xf1: - break; - case 0xf2: - getnext (2); - break; - case 0xf3: - getnext (1); - break; - case 0xf4: - break; - case 0xf5: - break; - case 0xf6: /*something */ - case 0xf8: - case 0xfa: - case 0xfb: - case 0xfc: - //this ends the track for sierra. - if (type == FILE_SIERRA || type == FILE_ADVSIERRA) - { - track[curtrack].tend = pos; - midiprintf ("endmark: %lu -- %lx\n", pos, pos); - } - break; - case 0xfe: - break; - case 0xfd: - break; - case 0xff: - v = getnext (1); - l = getval (); - midiprintf ("\n"); - midiprintf ("{%lX_%lX}", v, l); - if (v == 0x51) + if (pos < track[curtrack].tend) { - lnum = getnext (l); - msqtr = lnum; /*set tempo */ - midiprintf ("(qtr=%ld)", msqtr); + if (type != FILE_SIERRA && type !=FILE_ADVSIERRA) + w=getval(); + else + w=getnext(1); + track[curtrack].iwait=w; + /* + if (w!=0) + { + midiprintf("\n<%d>",w); + f = +((float)w/(float)deltas)*((float)msqtr/(float)1000000); + if (doing==1) f=0; //not playing yet. don't wait yet + } + */ } else - { - for (i = 0; i < l; i++) - midiprintf ("%2lX ", getnext (1)); - } - break; - } - break; - default: - midiprintf ("%lX!", v); /* if we get down here, a error occurred */ - break; - } + track[curtrack].iwait=0; - if (pos < track[curtrack].tend) - { - if (type != FILE_SIERRA && type != FILE_ADVSIERRA) - w = getval (); - else - w = getnext (1); - track[curtrack].iwait = w; - /* - if (w!=0) - { - midiprintf("\n<%d>",w); - f = - ((float)w/(float)deltas)*((float)msqtr/(float)1000000); - if (doing==1) f=0; //not playing yet. don't wait yet - } - */ + track[curtrack].pos=pos; } - else - track[curtrack].iwait = 0; - track[curtrack].pos = pos; - } + ret=0; //end of song. + iwait=0; + for (curtrack=0; curtrack<16; curtrack++) + if (track[curtrack].on == 1 && + track[curtrack].pos < track[curtrack].tend) + ret=1; //not yet.. - ret = 0; //end of song. - iwait = 0; - for (curtrack = 0; curtrack < 16; curtrack++) - if (track[curtrack].on == 1 && - track[curtrack].pos < track[curtrack].tend) - ret = 1; //not yet.. + if (ret==1) + { + iwait=0xffffff; // bigger than any wait can be! + for (curtrack=0; curtrack<16; curtrack++) + if (track[curtrack].on == 1 && + track[curtrack].pos < track[curtrack].tend && + track[curtrack].iwait < iwait) + iwait=track[curtrack].iwait; + } + } - if (ret == 1) - { - iwait = 0xffffff; // bigger than any wait can be! - for (curtrack = 0; curtrack < 16; curtrack++) - if (track[curtrack].on == 1 && - track[curtrack].pos < track[curtrack].tend && - track[curtrack].iwait < iwait) - iwait = track[curtrack].iwait; - } - } + if (iwait !=0 && ret==1) + { + for (curtrack=0; curtrack<16; curtrack++) + if (track[curtrack].on) + track[curtrack].iwait-=iwait; - if (iwait != 0 && ret == 1) - { - for (curtrack = 0; curtrack < 16; curtrack++) - if (track[curtrack].on) - track[curtrack].iwait -= iwait; +fwait=1.0f/(((float)iwait/(float)deltas)*((float)msqtr/(float)1000000)); + } + else + fwait=50; // 1/50th of a second - fwait = - 1.0f / (((float) iwait / (float) deltas) * - ((float) msqtr / (float) 1000000)); - } - else - fwait = 50; // 1/50th of a second + midiprintf ("\n"); + for (i=0; i<16; i++) + if (track[i].on) { + if (track[i].pos < track[i].tend) + midiprintf ("<%lu>",track[i].iwait); + else + midiprintf("stop"); + } - midiprintf ("\n"); - for (i = 0; i < 16; i++) - if (track[i].on) - { - if (track[i].pos < track[i].tend) - midiprintf ("<%lu>", track[i].iwait); - else - midiprintf ("stop"); - } + /* + if (ret==0 && type==FILE_ADVSIERRA) + if (datalook(sierra_pos-2)!=0xff) + { + midiprintf ("next sectoin!"); + sierra_next_section(p); + fwait=50; + ret=1; + } + */ - /* - if (ret==0 && type==FILE_ADVSIERRA) - if (datalook(sierra_pos-2)!=0xff) - { - midiprintf ("next sectoin!"); - sierra_next_section(p); - fwait=50; - ret=1; - } - */ - - if (ret) - return true; - else - return false; + if(ret) + return true; + else + return false; } -float -CmidPlayer::getrefresh () +float CmidPlayer::getrefresh() { - return (fwait > 0.01f ? fwait : 0.01f); + return (fwait > 0.01f ? fwait : 0.01f); } -void -CmidPlayer::rewind (int subsong) +void CmidPlayer::rewind(int subsong) { - long i, j, l; - long o_sierra_pos; - unsigned char ins[16]; - - pos = 0; - tins = 0; - adlib_style = MIDI_STYLE | CMF_STYLE; - adlib_mode = ADLIB_MELODIC; - for (i = 0; i < 128; i++) - for (j = 0; j < 14; j++) // for (j = 0; j < 16; j++) - myinsbank[i][j] = midi_fm_instruments[i][j]; - for (i = 0; i < 16; i++) - { - ch[i].inum = 0; - for (j = 0; j < 11; j++) - ch[i].ins[j] = myinsbank[ch[i].inum][j]; - ch[i].vol = 127; - ch[i].nshift = -25; - ch[i].on = 1; - } - - /* General init */ - for (i = 0; i < 9; i++) - { - chp[i][0] = -1; - chp[i][2] = 0; - } - - deltas = 250; // just a number, not a standard - msqtr = 500000; - fwait = 123; // gotta be a small thing.. sorta like nothing - iwait = 0; - - subsongs = 1; - - for (i = 0; i < 16; i++) - { - track[i].tend = 0; - track[i].spos = 0; - track[i].pos = 0; - track[i].iwait = 0; - track[i].on = 0; - track[i].pv = 0; - } - curtrack = 0; - - /* specific to file-type init */ - - pos = 0; - i = getnext (1); - switch (type) - { - case FILE_LUCAS: - getnext (24); //skip junk and get to the midi. - adlib_style = LUCAS_STYLE | MIDI_STYLE; - //note: no break, we go right into midi headers... - case FILE_MIDI: - if (type != FILE_LUCAS) - tins = 128; - getnext (11); /*skip header */ - deltas = getnext (2); - midiprintf ("deltas:%ld\n", deltas); - getnext (4); - - curtrack = 0; - track[curtrack].on = 1; - track[curtrack].tend = getnext (4); - track[curtrack].spos = pos; - midiprintf ("tracklen:%lu\n", track[curtrack].tend); - break; - case FILE_OLDLUCAS: - msqtr = 250000; - pos = 9; - deltas = getnext (1); - - i = 8; - pos = 0x19; // jump to instruments - tins = i; - for (j = 0; j < i; j++) - { - midiprintf ("\n%ld: ", j); - for (l = 0; l < 16; l++) - ins[l] = (unsigned char) getnext (1); - - myinsbank[j][10] = ins[2]; - myinsbank[j][0] = ins[3]; - myinsbank[j][2] = ins[4]; - myinsbank[j][4] = ins[5]; - myinsbank[j][6] = ins[6]; - myinsbank[j][8] = ins[7]; - myinsbank[j][1] = ins[8]; - myinsbank[j][3] = ins[9]; - myinsbank[j][5] = ins[10]; - myinsbank[j][7] = ins[11]; - myinsbank[j][9] = ins[12]; - - for (l = 0; l < 11; l++) - midiprintf ("%2X ", myinsbank[j][l]); - } - - for (i = 0; i < 16; i++) - { - if (i < tins) - { - ch[i].inum = i; - for (j = 0; j < 11; j++) - ch[i].ins[j] = myinsbank[ch[i].inum][j]; - } - } - - adlib_style = LUCAS_STYLE | MIDI_STYLE; - - curtrack = 0; - track[curtrack].on = 1; - track[curtrack].tend = flen; // music until the end of the file - track[curtrack].spos = 0x98; //jump to midi music - break; - case FILE_ADVSIERRA: - memcpy (myinsbank, smyinsbank, 128 * 16); - tins = stins; - deltas = 0x20; - getnext (11); //worthless empty space and "stuff" :) - - o_sierra_pos = sierra_pos = pos; - sierra_next_section (); - while (datalook (sierra_pos - 2) != 0xff) - { - sierra_next_section (); - subsongs++; - } + long i,j,n,m,l; + long o_sierra_pos; + unsigned char ins[16]; + + pos=0; tins=0; + adlib_style=MIDI_STYLE|CMF_STYLE; + adlib_mode=ADLIB_MELODIC; + for (i=0; i<128; i++) + for (j=0; j<16; j++) + myinsbank[i][j]=midi_fm_instruments[i][j]; + for (i=0; i<16; i++) + { + ch[i].inum=0; + for (j=0; j<11; j++) + ch[i].ins[j]=myinsbank[ch[i].inum][j]; + ch[i].vol=127; + ch[i].nshift=-25; + ch[i].on=1; + } - if (subsong < 0 || subsong >= subsongs) - subsong = 0; + /* General init */ + for (i=0; i<9; i++) + { + chp[i][0]=-1; + chp[i][2]=0; + } - sierra_pos = o_sierra_pos; - sierra_next_section (); - i = 0; - while (i != subsong) - { - sierra_next_section (); - i++; - } + deltas=250; // just a number, not a standard + msqtr=500000; + fwait=123; // gotta be a small thing.. sorta like nothing + iwait=0; - adlib_style = SIERRA_STYLE | MIDI_STYLE; //advanced sierra tunes use volume - break; - case FILE_SIERRA: - memcpy (myinsbank, smyinsbank, 128 * 16); - tins = stins; - getnext (2); - deltas = 0x20; + subsongs=1; - curtrack = 0; - track[curtrack].on = 1; - track[curtrack].tend = flen; // music until the end of the file + for (i=0; i<16; i++) + { + track[i].tend=0; + track[i].spos=0; + track[i].pos=0; + track[i].iwait=0; + track[i].on=0; + track[i].pv=0; + } + curtrack=0; - for (i = 0; i < 16; i++) - { - ch[i].nshift = -13; - ch[i].on = getnext (1); - ch[i].inum = getnext (1); - for (j = 0; j < 11; j++) - ch[i].ins[j] = myinsbank[ch[i].inum][j]; - } + /* specific to file-type init */ - track[curtrack].spos = pos; - adlib_style = SIERRA_STYLE | MIDI_STYLE; - break; - } + pos=0; + i=getnext(1); + switch(type) + { + case FILE_LUCAS: + getnext(24); //skip junk and get to the midi. + adlib_style=LUCAS_STYLE|MIDI_STYLE; + //note: no break, we go right into midi headers... + case FILE_MIDI: + if (type != FILE_LUCAS) + tins=128; + getnext(11); /*skip header*/ + deltas=getnext(2); + midiprintf ("deltas:%ld\n",deltas); + getnext(4); + + curtrack=0; + track[curtrack].on=1; + track[curtrack].tend=getnext(4); + track[curtrack].spos=pos; + midiprintf ("tracklen:%lu\n",track[curtrack].tend); + break; + case FILE_CMF: + getnext(3); // ctmf + getnexti(2); //version + n=getnexti(2); // instrument offset + m=getnexti(2); // music offset + deltas=getnexti(2); //ticks/qtr note + msqtr=1000000/getnexti(2)*deltas; + //the stuff in the cmf is click ticks per second.. + + i=getnexti(2); + if(i) title = (char *)data+i; + i=getnexti(2); + if(i) author = (char *)data+i; + i=getnexti(2); + if(i) remarks = (char *)data+i; + + getnext(16); // channel in use table .. + i=getnexti(2); // num instr + if (i>128) i=128; // to ward of bad numbers... + getnexti(2); //basic tempo + + midiprintf("\nioff:%ld\nmoff%ld\ndeltas:%ld\nmsqtr:%ld\nnumi:%ld\n", + n,m,deltas,msqtr,i); + pos=n; // jump to instruments + tins=i; + for (j=0; j<i; j++) + { + midiprintf ("\n%ld: ",j); + for (l=0; l<16; l++) + { + myinsbank[j][l]=(unsigned char)getnext(1); + midiprintf ("%2X ",myinsbank[j][l]); + } + } + + for (i=0; i<16; i++) + ch[i].nshift=-13; + + adlib_style=CMF_STYLE; + + curtrack=0; + track[curtrack].on=1; + track[curtrack].tend=flen; // music until the end of the file + track[curtrack].spos=m; //jump to midi music + break; + case FILE_OLDLUCAS: + msqtr=250000; + pos=9; + deltas=getnext(1); + + i=8; + pos=0x19; // jump to instruments + tins=i; + for (j=0; j<i; j++) + { + midiprintf ("\n%ld: ",j); + for (l=0; l<16; l++) + ins[l]=(unsigned char)getnext(1); + + myinsbank[j][10]=ins[2]; + myinsbank[j][0]=ins[3]; + myinsbank[j][2]=ins[4]; + myinsbank[j][4]=ins[5]; + myinsbank[j][6]=ins[6]; + myinsbank[j][8]=ins[7]; + myinsbank[j][1]=ins[8]; + myinsbank[j][3]=ins[9]; + myinsbank[j][5]=ins[10]; + myinsbank[j][7]=ins[11]; + myinsbank[j][9]=ins[12]; + + for (l=0; l<11; l++) + midiprintf ("%2X ",myinsbank[j][l]); + } + + for (i=0; i<16; i++) + { + if (i<tins) + { + ch[i].inum=i; + for (j=0; j<11; j++) + ch[i].ins[j]=myinsbank[ch[i].inum][j]; + } + } + + adlib_style=LUCAS_STYLE|MIDI_STYLE; + + curtrack=0; + track[curtrack].on=1; + track[curtrack].tend=flen; // music until the end of the file + track[curtrack].spos=0x98; //jump to midi music + break; + case FILE_ADVSIERRA: + memcpy(myinsbank, smyinsbank, 128 * 16); + tins = stins; + deltas=0x20; + getnext(11); //worthless empty space and "stuff" :) + + o_sierra_pos=sierra_pos=pos; + sierra_next_section(); + while (datalook(sierra_pos-2)!=0xff) + { + sierra_next_section(); + subsongs++; + } + + if (subsong < 0 || subsong >= subsongs) subsong=0; + + sierra_pos=o_sierra_pos; + sierra_next_section(); + i=0; + while (i != subsong) + { + sierra_next_section(); + i++; + } + + adlib_style=SIERRA_STYLE|MIDI_STYLE; //advanced sierra tunes use volume + break; + case FILE_SIERRA: + memcpy(myinsbank, smyinsbank, 128 * 16); + tins = stins; + getnext(2); + deltas=0x20; + + curtrack=0; + track[curtrack].on=1; + track[curtrack].tend=flen; // music until the end of the file + + for (i=0; i<16; i++) + { + ch[i].nshift=-13; + ch[i].on=getnext(1); + ch[i].inum=getnext(1); + for (j=0; j<11; j++) + ch[i].ins[j]=myinsbank[ch[i].inum][j]; + } + + track[curtrack].spos=pos; + adlib_style=SIERRA_STYLE|MIDI_STYLE; + break; + } /* sprintf(info,"%s\r\nTicks/Quarter Note: %ld\r\n",info,deltas); sprintf(info,"%sms/Quarter Note: %ld",info,msqtr); */ - for (i = 0; i < 16; i++) - if (track[i].on) - { - track[i].pos = track[i].spos; - track[i].pv = 0; - track[i].iwait = 0; - } + for (i=0; i<16; i++) + if (track[i].on) + { + track[i].pos=track[i].spos; + track[i].pv=0; + track[i].iwait=0; + } - doing = 1; - midi_fm_reset (); + doing=1; + midi_fm_reset(); } -std::string CmidPlayer::gettype () +std::string CmidPlayer::gettype() { - switch (type) - { - case FILE_LUCAS: - return std::string ("LucasArts AdLib MIDI"); - case FILE_MIDI: - return std::string ("General MIDI"); - case FILE_OLDLUCAS: - return std::string ("Lucasfilm Adlib MIDI"); - case FILE_ADVSIERRA: - return std::string ("Sierra On-Line VGA MIDI"); - case FILE_SIERRA: - return std::string ("Sierra On-Line EGA MIDI"); - default: - return std::string ("MIDI unknown"); - } + switch(type) { + case FILE_LUCAS: + return std::string("LucasArts AdLib MIDI"); + case FILE_MIDI: + return std::string("General MIDI"); + case FILE_CMF: + return std::string("Creative Music Format (CMF MIDI)"); + case FILE_OLDLUCAS: + return std::string("Lucasfilm Adlib MIDI"); + case FILE_ADVSIERRA: + return std::string("Sierra On-Line VGA MIDI"); + case FILE_SIERRA: + return std::string("Sierra On-Line EGA MIDI"); + default: + return std::string("MIDI unknown"); + } } diff --git a/src/adplug/core/mid.h b/src/adplug/core/mid.h index 737bd70..04bed21 100644 --- a/src/adplug/core/mid.h +++ b/src/adplug/core/mid.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. - * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * Copyright (C) 1999 - 2008 Simon Peter, <dn.tlp@gmx.net>, et al. + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -30,7 +30,7 @@ public: ~CmidPlayer() { if(data) delete [] data; } - bool load(VFSFile &fd, const CFileProvider &fp); + bool load(const std::string &filename, const CFileProvider &fp); bool update(); void rewind(int subsong); float getrefresh(); diff --git a/src/adplug/core/mididata.h b/src/adplug/core/mididata.h index 7817c35..cab4d27 100644 --- a/src/adplug/core/mididata.h +++ b/src/adplug/core/mididata.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999, 2000, 2001 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -21,8 +21,8 @@ * Phil Hassey, <philhassey@hotmail.com> - see "adplug/players/mid.cpp" * for further acknowledgements. */ - -unsigned char midi_fm_instruments[128][14] = + +unsigned char midi_fm_instruments[128][16] = { /* This set of GM instrument patches was provided by Jorrit Rouwe... diff --git a/src/adplug/core/mkj.cc b/src/adplug/core/mkj.cc index de4bf2d..f19a14c 100644 --- a/src/adplug/core/mkj.cc +++ b/src/adplug/core/mkj.cc @@ -19,195 +19,135 @@ * mkj.cpp - MKJamz Player, by Simon Peter <dn.tlp@gmx.net> */ +#include <cstring> #include <assert.h> -#include <string.h> #include "mkj.h" #include "debug.h" -CPlayer * -CmkjPlayer::factory (Copl * newopl) +CPlayer *CmkjPlayer::factory(Copl *newopl) { - return new CmkjPlayer (newopl); + return new CmkjPlayer(newopl); } -bool -CmkjPlayer::load (VFSFile & fd, const CFileProvider & fp) +bool CmkjPlayer::load(const std::string &filename, const CFileProvider &fp) { - binistream *f = fp.open (fd); - if (!f) - return false; - char id[6]; + binistream *f = fp.open(filename); if(!f) return false; + char id[6]; float ver; - int i, j; + int i, j; short inst[8]; // file validation - f->readString (id, 6); - if (strncmp (id, "MKJamz", 6)) - { - fp.close (f); - return false; - } - ver = f->readFloat (binio::Single); - if (ver > 1.12) - { - fp.close (f); - return false; - } + f->readString(id, 6); + if(strncmp(id,"MKJamz",6)) { fp.close(f); return false; } + ver = f->readFloat(binio::Single); + if(ver > 1.12) { fp.close(f); return false; } // load - maxchannel = f->readInt (2); - opl->init (); - opl->write (1, 32); - for (i = 0; i < maxchannel; i++) - { - for (j = 0; j < 8; j++) - inst[j] = f->readInt (2); - opl->write (0x20 + op_table[i], inst[4]); - opl->write (0x23 + op_table[i], inst[0]); - opl->write (0x40 + op_table[i], inst[5]); - opl->write (0x43 + op_table[i], inst[1]); - opl->write (0x60 + op_table[i], inst[6]); - opl->write (0x63 + op_table[i], inst[2]); - opl->write (0x80 + op_table[i], inst[7]); - opl->write (0x83 + op_table[i], inst[3]); + maxchannel = f->readInt(2); + opl->init(); opl->write(1, 32); + for(i = 0; i < maxchannel; i++) { + for(j = 0; j < 8; j++) inst[j] = f->readInt(2); + opl->write(0x20+op_table[i],inst[4]); + opl->write(0x23+op_table[i],inst[0]); + opl->write(0x40+op_table[i],inst[5]); + opl->write(0x43+op_table[i],inst[1]); + opl->write(0x60+op_table[i],inst[6]); + opl->write(0x63+op_table[i],inst[2]); + opl->write(0x80+op_table[i],inst[7]); + opl->write(0x83+op_table[i],inst[3]); } - maxnotes = f->readInt (2); - songbuf = new short[(maxchannel + 1) * maxnotes]; - for (i = 0; i < maxchannel; i++) - channel[i].defined = f->readInt (2); - for (i = 0; i < (maxchannel + 1) * maxnotes; i++) - songbuf[i] = f->readInt (2); - - AdPlug_LogWrite - ("CmkjPlayer::load(\"%s\"): loaded file ver %.2f, %d channels," - " %d notes/channel.\n", fd.filename (), ver, maxchannel, maxnotes); - fp.close (f); - rewind (0); + maxnotes = f->readInt(2); + songbuf = new short [(maxchannel+1)*maxnotes]; + for(i = 0; i < maxchannel; i++) channel[i].defined = f->readInt(2); + for(i = 0; i < (maxchannel + 1) * maxnotes; i++) + songbuf[i] = f->readInt(2); + + AdPlug_LogWrite("CmkjPlayer::load(\"%s\"): loaded file ver %.2f, %d channels," + " %d notes/channel.\n", filename.c_str(), ver, maxchannel, + maxnotes); + fp.close(f); + rewind(0); return true; } -bool -CmkjPlayer::update () +bool CmkjPlayer::update() { int c, i; short note; - for (c = 0; c < maxchannel; c++) - { - if (!channel[c].defined) // skip if channel is disabled + for(c = 0; c < maxchannel; c++) { + if(!channel[c].defined) // skip if channel is disabled continue; - if (channel[c].pstat) - { + if(channel[c].pstat) { channel[c].pstat--; continue; } - opl->write (0xb0 + c, 0); // key off - do - { - assert (channel[c].songptr < (maxchannel + 1) * maxnotes); + opl->write(0xb0 + c, 0); // key off + do { + assert(channel[c].songptr < (maxchannel + 1) * maxnotes); note = songbuf[channel[c].songptr]; - if (channel[c].songptr - c > maxchannel) - if (note && note < 250) + if(channel[c].songptr - c > maxchannel) + if(note && note < 250) channel[c].pstat = channel[c].speed; - switch (note) - { + switch(note) { // normal notes - case 68: - opl->write (0xa0 + c, 0x81); - opl->write (0xb0 + c, 0x21 + 4 * channel[c].octave); - break; - case 69: - opl->write (0xa0 + c, 0xb0); - opl->write (0xb0 + c, 0x21 + 4 * channel[c].octave); - break; - case 70: - opl->write (0xa0 + c, 0xca); - opl->write (0xb0 + c, 0x21 + 4 * channel[c].octave); - break; - case 71: - opl->write (0xa0 + c, 0x2); - opl->write (0xb0 + c, 0x22 + 4 * channel[c].octave); - break; - case 65: - opl->write (0xa0 + c, 0x41); - opl->write (0xb0 + c, 0x22 + 4 * channel[c].octave); - break; - case 66: - opl->write (0xa0 + c, 0x87); - opl->write (0xb0 + c, 0x22 + 4 * channel[c].octave); - break; - case 67: - opl->write (0xa0 + c, 0xae); - opl->write (0xb0 + c, 0x22 + 4 * channel[c].octave); - break; - case 17: - opl->write (0xa0 + c, 0x6b); - opl->write (0xb0 + c, 0x21 + 4 * channel[c].octave); - break; - case 18: - opl->write (0xa0 + c, 0x98); - opl->write (0xb0 + c, 0x21 + 4 * channel[c].octave); - break; - case 20: - opl->write (0xa0 + c, 0xe5); - opl->write (0xb0 + c, 0x21 + 4 * channel[c].octave); - break; - case 21: - opl->write (0xa0 + c, 0x20); - opl->write (0xb0 + c, 0x22 + 4 * channel[c].octave); - break; - case 15: - opl->write (0xa0 + c, 0x63); - opl->write (0xb0 + c, 0x22 + 4 * channel[c].octave); - break; - case 255: // delay + case 68: opl->write(0xa0 + c,0x81); opl->write(0xb0 + c,0x21 + 4 * channel[c].octave); break; + case 69: opl->write(0xa0 + c,0xb0); opl->write(0xb0 + c,0x21 + 4 * channel[c].octave); break; + case 70: opl->write(0xa0 + c,0xca); opl->write(0xb0 + c,0x21 + 4 * channel[c].octave); break; + case 71: opl->write(0xa0 + c,0x2); opl->write(0xb0 + c,0x22 + 4 * channel[c].octave); break; + case 65: opl->write(0xa0 + c,0x41); opl->write(0xb0 + c,0x22 + 4 * channel[c].octave); break; + case 66: opl->write(0xa0 + c,0x87); opl->write(0xb0 + c,0x22 + 4 * channel[c].octave); break; + case 67: opl->write(0xa0 + c,0xae); opl->write(0xb0 + c,0x22 + 4 * channel[c].octave); break; + case 17: opl->write(0xa0 + c,0x6b); opl->write(0xb0 + c,0x21 + 4 * channel[c].octave); break; + case 18: opl->write(0xa0 + c,0x98); opl->write(0xb0 + c,0x21 + 4 * channel[c].octave); break; + case 20: opl->write(0xa0 + c,0xe5); opl->write(0xb0 + c,0x21 + 4 * channel[c].octave); break; + case 21: opl->write(0xa0 + c,0x20); opl->write(0xb0 + c,0x22 + 4 * channel[c].octave); break; + case 15: opl->write(0xa0 + c,0x63); opl->write(0xb0 + c,0x22 + 4 * channel[c].octave); break; + case 255: // delay channel[c].songptr += maxchannel; channel[c].pstat = songbuf[channel[c].songptr]; break; - case 254: // set octave + case 254: // set octave channel[c].songptr += maxchannel; channel[c].octave = songbuf[channel[c].songptr]; break; - case 253: // set speed + case 253: // set speed channel[c].songptr += maxchannel; channel[c].speed = songbuf[channel[c].songptr]; break; - case 252: // set waveform + case 252: // set waveform channel[c].songptr += maxchannel; channel[c].waveform = songbuf[channel[c].songptr] - 300; - if (c > 2) - opl->write (0xe0 + c + (c + 6), channel[c].waveform); + if(c > 2) + opl->write(0xe0 + c + (c+6),channel[c].waveform); else - opl->write (0xe0 + c, channel[c].waveform); + opl->write(0xe0 + c,channel[c].waveform); break; - case 251: // song end - for (i = 0; i < maxchannel; i++) - channel[i].songptr = i; + case 251: // song end + for(i = 0; i < maxchannel; i++) channel[i].songptr = i; songend = true; return false; } - if (channel[c].songptr - c < maxnotes) + if(channel[c].songptr - c < maxnotes) channel[c].songptr += maxchannel; else channel[c].songptr = c; - } while (!channel[c].pstat); + } while(!channel[c].pstat); } return !songend; } -void -CmkjPlayer::rewind (int subsong) +void CmkjPlayer::rewind(int subsong) { int i; - for (i = 0; i < maxchannel; i++) - { + for(i = 0; i < maxchannel; i++) { channel[i].pstat = 0; channel[i].speed = 0; channel[i].waveform = 0; @@ -218,8 +158,7 @@ CmkjPlayer::rewind (int subsong) songend = false; } -float -CmkjPlayer::getrefresh () +float CmkjPlayer::getrefresh() { return 100.0f; } diff --git a/src/adplug/core/mkj.h b/src/adplug/core/mkj.h index 7480128..edb857f 100644 --- a/src/adplug/core/mkj.h +++ b/src/adplug/core/mkj.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -26,25 +26,25 @@ class CmkjPlayer: public CPlayer public: static CPlayer *factory(Copl *newopl); - CmkjPlayer(Copl *newopl) - : CPlayer(newopl), songbuf(0) - { } - ~CmkjPlayer() - { if(songbuf) delete [] songbuf; } + CmkjPlayer(Copl *newopl) + : CPlayer(newopl), songbuf(0) + { } + ~CmkjPlayer() + { if(songbuf) delete [] songbuf; } - bool load(VFSFile &fd, const CFileProvider &fp); - bool update(); - void rewind(int subsong); - float getrefresh(); + bool load(const std::string &filename, const CFileProvider &fp); + bool update(); + void rewind(int subsong); + float getrefresh(); - std::string gettype() - { return std::string("MKJamz Audio File"); } + std::string gettype() + { return std::string("MKJamz Audio File"); } private: - short maxchannel,maxnotes,*songbuf; - bool songend; + short maxchannel,maxnotes,*songbuf; + bool songend; - struct { - short defined,songptr,octave,waveform,pstat,speed,delay; - } channel[9]; + struct { + short defined,songptr,octave,waveform,pstat,speed,delay; + } channel[9]; }; diff --git a/src/adplug/core/msc.cc b/src/adplug/core/msc.cc index 7b04a97..ddf09c7 100644 --- a/src/adplug/core/msc.cc +++ b/src/adplug/core/msc.cc @@ -19,68 +19,61 @@ * msc.c - MSC Player by Lubomir Bulej (pallas@kadan.cz) */ +#include <cstring> #include <stdio.h> -#include <string.h> #include "msc.h" #include "debug.h" -const unsigned char - CmscPlayer::msc_signature[MSC_SIGN_LEN] = { +const unsigned char CmscPlayer::msc_signature [MSC_SIGN_LEN] = { 'C', 'e', 'r', 'e', 's', ' ', '\x13', ' ', - 'M', 'S', 'C', 'p', 'l', 'a', 'y', ' ' -}; + 'M', 'S', 'C', 'p', 'l', 'a', 'y', ' ' }; /*** public methods *************************************/ -CPlayer * -CmscPlayer::factory (Copl * newopl) +CPlayer *CmscPlayer::factory (Copl * newopl) { return new CmscPlayer (newopl); } -CmscPlayer::CmscPlayer (Copl * newopl):CPlayer (newopl) +CmscPlayer::CmscPlayer(Copl * newopl) : CPlayer (newopl) { - desc = nullptr; - msc_data = nullptr; - raw_data = nullptr; + desc = NULL; + msc_data = NULL; + raw_data = NULL; nr_blocks = 0; } -CmscPlayer::~CmscPlayer () +CmscPlayer::~CmscPlayer() { - if (raw_data != nullptr) - delete[]raw_data; + if (raw_data != NULL) + delete [] raw_data; - if (msc_data != nullptr) - { + if (msc_data != NULL) { // free compressed blocks - for (int blk_num = 0; blk_num < nr_blocks; blk_num++) - { - if (msc_data[blk_num].mb_data != nullptr) - delete[]msc_data[blk_num].mb_data; + for (int blk_num = 0; blk_num < nr_blocks; blk_num++) { + if (msc_data [blk_num].mb_data != NULL) + delete [] msc_data [blk_num].mb_data; } - delete[]msc_data; + delete [] msc_data; } - if (desc != nullptr) - delete[]desc; + if (desc != NULL) + delete [] desc; } -bool -CmscPlayer::load (VFSFile & fd, const CFileProvider & fp) +bool CmscPlayer::load(const std::string & filename, const CFileProvider & fp) { - binistream *bf; - msc_header hdr; + binistream * bf; + msc_header hdr; // open and validate the file - bf = fp.open (fd); - if (!bf) + bf = fp.open (filename); + if (! bf) return false; - if (!load_header (bf, &hdr)) - { + if (! load_header (bf, & hdr)) { fp.close (bf); return false; } @@ -91,28 +84,25 @@ CmscPlayer::load (VFSFile & fd, const CFileProvider & fp) nr_blocks = hdr.mh_nr_blocks; block_len = hdr.mh_block_len; - if (!nr_blocks) - { + if (! nr_blocks) { fp.close (bf); return false; } // load compressed data blocks - msc_data = new msc_block[nr_blocks]; - raw_data = new u8[block_len]; + msc_data = new msc_block [nr_blocks]; + raw_data = new u8 [block_len]; - for (int blk_num = 0; blk_num < nr_blocks; blk_num++) - { + for (int blk_num = 0; blk_num < nr_blocks; blk_num++) { msc_block blk; blk.mb_length = bf->readInt (2); - blk.mb_data = new u8[blk.mb_length]; - for (int oct_num = 0; oct_num < blk.mb_length; oct_num++) - { - blk.mb_data[oct_num] = bf->readInt (1); + blk.mb_data = new u8 [blk.mb_length]; + for (int oct_num = 0; oct_num < blk.mb_length; oct_num++) { + blk.mb_data [oct_num] = bf->readInt (1); } - msc_data[blk_num] = blk; + msc_data [blk_num] = blk; } // clean up & initialize @@ -122,25 +112,22 @@ CmscPlayer::load (VFSFile & fd, const CFileProvider & fp) return true; } -bool -CmscPlayer::update () +bool CmscPlayer::update() { // output data - while (!delay) - { - u8 cmnd; - u8 data; + while (! delay) { + u8 cmnd; + u8 data; // decode data - if (!decode_octet (&cmnd)) + if (! decode_octet (& cmnd)) return false; - if (!decode_octet (&data)) + if (! decode_octet (& data)) return false; // check for special commands - switch (cmnd) - { + switch (cmnd) { // delay case 0xff: @@ -151,8 +138,8 @@ CmscPlayer::update () default: opl->write (cmnd, data); - } // command switch - } // play pass + } // command switch + } // play pass // count delays @@ -164,8 +151,7 @@ CmscPlayer::update () return true; } -void -CmscPlayer::rewind (int subsong) +void CmscPlayer::rewind(int subsong) { // reset state dec_prefix = 0; @@ -176,30 +162,27 @@ CmscPlayer::rewind (int subsong) delay = 0; // init the OPL chip and go to OPL2 mode - opl->init (); - opl->write (1, 32); + opl->init(); + opl->write(1, 32); } -float -CmscPlayer::getrefresh () +float CmscPlayer::getrefresh() { // PC timer oscillator frequency / wait register return 1193180 / (float) (timer_div ? timer_div : 0xffff); } -std::string CmscPlayer::gettype () +std::string CmscPlayer::gettype() { - char - vstr[40]; + char vstr [40]; - sprintf (vstr, "AdLib MSCplay (version %d)", version); + sprintf(vstr, "AdLib MSCplay (version %d)", version); return std::string (vstr); } /*** private methods *************************************/ -bool -CmscPlayer::load_header (binistream * bf, msc_header * hdr) +bool CmscPlayer::load_header(binistream * bf, msc_header * hdr) { // check signature bf->readString ((char *) hdr->mh_sign, sizeof (hdr->mh_sign)); @@ -218,42 +201,37 @@ CmscPlayer::load_header (binistream * bf, msc_header * hdr) return true; } -bool -CmscPlayer::decode_octet (u8 * output) +bool CmscPlayer::decode_octet(u8 * output) { - msc_block blk; // compressed data block + msc_block blk; // compressed data block if (block_num >= nr_blocks) return false; - blk = msc_data[block_num]; - while (1) - { - u8 octet; // decoded octet - u8 len_corr = 0; // length correction + blk = msc_data [block_num]; + while (1) { + u8 octet; // decoded octet + u8 len_corr = 0; // length correction // advance to next block if necessary - if (block_pos >= blk.mb_length && dec_len == 0) - { + if (block_pos >= blk.mb_length && dec_len == 0) { block_num++; if (block_num >= nr_blocks) return false; - blk = msc_data[block_num]; + blk = msc_data [block_num]; block_pos = 0; raw_pos = 0; } // decode the compressed music data - switch (dec_prefix) - { + switch (dec_prefix) { // decode prefix case 155: case 175: - octet = blk.mb_data[block_pos++]; - if (octet == 0) - { + octet = blk.mb_data [block_pos++]; + if (octet == 0) { // invalid prefix, output original octet = dec_prefix; dec_prefix = 0; @@ -276,7 +254,7 @@ CmscPlayer::decode_octet (u8 * output) // check for extended length case 156: if (dec_len == 15) - dec_len += blk.mb_data[block_pos++]; + dec_len += blk.mb_data [block_pos++]; // add length correction and go for copy mode dec_len += len_corr; @@ -286,7 +264,7 @@ CmscPlayer::decode_octet (u8 * output) // get extended distance case 176: - dec_dist += 17 + 16 * blk.mb_data[block_pos++]; + dec_dist += 17 + 16 * blk.mb_data [block_pos++]; len_corr = 3; // check for extended length @@ -296,17 +274,15 @@ CmscPlayer::decode_octet (u8 * output) // prefix copy mode case 255: - if ((int) raw_pos >= dec_dist) - octet = raw_data[raw_pos - dec_dist]; - else - { - AdPlug_LogWrite ("error! read before raw_data buffer.\n"); + if((int)raw_pos >= dec_dist) + octet = raw_data [raw_pos - dec_dist]; + else { + AdPlug_LogWrite("error! read before raw_data buffer.\n"); octet = 0; } dec_len--; - if (dec_len == 0) - { + if (dec_len == 0) { // back to normal mode dec_prefix = 0; } @@ -316,23 +292,22 @@ CmscPlayer::decode_octet (u8 * output) // normal mode default: - octet = blk.mb_data[block_pos++]; - if (octet == 155 || octet == 175) - { + octet = blk.mb_data [block_pos++]; + if (octet == 155 || octet == 175) { // it's a prefix, restart dec_prefix = octet; continue; } - } // prefix switch + } // prefix switch // output the octet - if (output != nullptr) + if (output != NULL) *output = octet; - raw_data[raw_pos++] = octet; + raw_data [raw_pos++] = octet; break; - }; // decode pass + }; // decode pass return true; } diff --git a/src/adplug/core/msc.h b/src/adplug/core/msc.h index 67b3fb5..b6cf6ec 100644 --- a/src/adplug/core/msc.h +++ b/src/adplug/core/msc.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. - * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * Copyright (C) 1999 - 2006 Simon Peter, <dn.tlp@gmx.net>, et al. + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -21,70 +21,67 @@ #include "player.h" -#define MSC_SIGN_LEN 16 -#define MSC_DESC_LEN 64 +#define MSC_SIGN_LEN 16 +#define MSC_DESC_LEN 64 class CmscPlayer: public CPlayer { -public: - static CPlayer * factory (Copl * newopl); + public: + static CPlayer * factory(Copl * newopl); + + CmscPlayer(Copl * newopl); + ~CmscPlayer(); + + bool load(const std::string &filename, const CFileProvider &fp); + bool update(); + void rewind(int subsong); + float getrefresh(); + + std::string gettype (); - CmscPlayer (Copl * newopl); - ~CmscPlayer (); - - bool load (VFSFile &fd, const CFileProvider &fp); - bool update (); - void rewind (int subsong); - float getrefresh (); + protected: + typedef unsigned char u8; + typedef unsigned short u16; - std::string gettype (); + struct msc_header { + u8 mh_sign [MSC_SIGN_LEN]; + u16 mh_ver; + u8 mh_desc [MSC_DESC_LEN]; + u16 mh_timer; + u16 mh_nr_blocks; + u16 mh_block_len; + }; + struct msc_block { + u16 mb_length; + u8 * mb_data; + }; -protected: - typedef unsigned char u8; - typedef unsigned short u16; + // file data + char * desc; // song desctiption + unsigned short version; // file version + unsigned short nr_blocks; // number of music blocks + unsigned short block_len; // maximal block length + unsigned short timer_div; // timer divisor + msc_block * msc_data; // compressed music data - struct msc_header { - u8 mh_sign [MSC_SIGN_LEN]; - u16 mh_ver; - u8 mh_desc [MSC_DESC_LEN]; - u16 mh_timer; - u16 mh_nr_blocks; - u16 mh_block_len; - }; + // decoder state + unsigned long block_num; // active block + unsigned long block_pos; // position in block + unsigned long raw_pos; // position in data buffer + u8 * raw_data; // decompression buffer - struct msc_block { - u16 mb_length; - u8 * mb_data; - }; - - - // file data - char * desc; // song desctiption - unsigned short version; // file version - unsigned short nr_blocks; // number of music blocks - unsigned short block_len; // maximal block length - unsigned short timer_div; // timer divisor - msc_block * msc_data; // compressed music data - - // decoder state - unsigned long block_num; // active block - unsigned long block_pos; // position in block - unsigned long raw_pos; // position in data buffer - u8 * raw_data; // decompression buffer + u8 dec_prefix; // prefix / state + int dec_dist; // prefix distance + unsigned int dec_len; // prefix length - u8 dec_prefix; // prefix / state - int dec_dist; // prefix distance - unsigned int dec_len; // prefix length - - // player state - unsigned char delay; // active delay - unsigned long play_pos; // player position - + // player state + unsigned char delay; // active delay + unsigned long play_pos; // player position -private: - static const u8 msc_signature [MSC_SIGN_LEN]; + private: + static const u8 msc_signature [MSC_SIGN_LEN]; - bool load_header (binistream * bf, msc_header * hdr); - bool decode_octet (u8 * output); + bool load_header (binistream * bf, msc_header * hdr); + bool decode_octet (u8 * output); }; diff --git a/src/adplug/core/mtk.cc b/src/adplug/core/mtk.cc index dc7c321..4f08f96 100644 --- a/src/adplug/core/mtk.cc +++ b/src/adplug/core/mtk.cc @@ -19,77 +19,61 @@ * mtk.cpp - MPU-401 Trakker Loader by Simon Peter (dn.tlp@gmx.net) */ -#include <string.h> - +#include <cstring> #include "mtk.h" /*** public methods **************************************/ -CPlayer * -CmtkLoader::factory (Copl * newopl) +CPlayer *CmtkLoader::factory(Copl *newopl) { - return new CmtkLoader (newopl); + return new CmtkLoader(newopl); } -bool -CmtkLoader::load (VFSFile & fd, const CFileProvider & fp) +bool CmtkLoader::load(const std::string &filename, const CFileProvider &fp) { - binistream *f = fp.open (fd); - if (!f) - return false; - struct - { + binistream *f = fp.open(filename); if(!f) return false; + struct { char id[18]; - unsigned short crc, size; + unsigned short crc,size; } header; - struct mtkdata - { - char songname[34], composername[34], instname[0x80][34]; - unsigned char insts[0x80][12], order[0x80], dummy, - patterns[0x32][0x40][9]; + struct mtkdata { + char songname[34],composername[34],instname[0x80][34]; + unsigned char insts[0x80][12],order[0x80],dummy,patterns[0x32][0x40][9]; } *data; - unsigned char *cmp, *org; + unsigned char *cmp,*org; unsigned int i; - unsigned long cmpsize, cmpptr = 0, orgptr = 0; - unsigned short ctrlbits = 0, ctrlmask = 0, cmd, cnt, offs; + unsigned long cmpsize,cmpptr=0,orgptr=0; + unsigned short ctrlbits=0,ctrlmask=0,cmd,cnt,offs; // read header - f->readString (header.id, 18); - header.crc = f->readInt (2); - header.size = f->readInt (2); + f->readString(header.id, 18); + header.crc = f->readInt(2); + header.size = f->readInt(2); // file validation section - if (strncmp (header.id, "mpu401tr\x92kk\xeer@data", 18)) - { - fp.close (f); - return false; - } + if(strncmp(header.id,"mpu401tr\x92kk\xeer@data",18)) + { fp.close(f); return false; } // load section - cmpsize = fp.filesize (f) - 22; + cmpsize = fp.filesize(f) - 22; cmp = new unsigned char[cmpsize]; org = new unsigned char[header.size]; - for (i = 0; i < cmpsize; i++) - cmp[i] = f->readInt (1); - fp.close (f); + for(i = 0; i < cmpsize; i++) cmp[i] = f->readInt(1); + fp.close(f); - while (cmpptr < cmpsize) - { // decompress + while(cmpptr < cmpsize) { // decompress ctrlmask >>= 1; - if (!ctrlmask) - { + if(!ctrlmask) { ctrlbits = cmp[cmpptr] + (cmp[cmpptr + 1] << 8); cmpptr += 2; ctrlmask = 0x8000; } - if (!(ctrlbits & ctrlmask)) - { // uncompressed data - if (orgptr >= header.size) + if(!(ctrlbits & ctrlmask)) { // uncompressed data + if(orgptr >= header.size) goto err; org[orgptr] = cmp[cmpptr]; - orgptr++; - cmpptr++; + orgptr++; cmpptr++; continue; } @@ -97,72 +81,61 @@ CmtkLoader::load (VFSFile & fd, const CFileProvider & fp) cmd = (cmp[cmpptr] >> 4) & 0x0f; cnt = cmp[cmpptr] & 0x0f; cmpptr++; - switch (cmd) - { + switch(cmd) { case 0: - if (orgptr + cnt > header.size) - goto err; + if(orgptr + cnt > header.size) goto err; cnt += 3; - memset (&org[orgptr], cmp[cmpptr], cnt); - cmpptr++; - orgptr += cnt; + memset(&org[orgptr],cmp[cmpptr],cnt); + cmpptr++; orgptr += cnt; break; case 1: - if (orgptr + cnt > header.size) - goto err; + if(orgptr + cnt > header.size) goto err; cnt += (cmp[cmpptr] << 4) + 19; - memset (&org[orgptr], cmp[++cmpptr], cnt); - cmpptr++; - orgptr += cnt; + memset(&org[orgptr],cmp[++cmpptr],cnt); + cmpptr++; orgptr += cnt; break; case 2: - if (orgptr + cnt > header.size) - goto err; - offs = (cnt + 3) + (cmp[cmpptr] << 4); - cnt = cmp[++cmpptr] + 16; - cmpptr++; - memcpy (&org[orgptr], &org[orgptr - offs], cnt); + if(orgptr + cnt > header.size) goto err; + offs = (cnt+3) + (cmp[cmpptr] << 4); + cnt = cmp[++cmpptr] + 16; cmpptr++; + memcpy(&org[orgptr],&org[orgptr - offs],cnt); orgptr += cnt; break; default: - if (orgptr + cmd > header.size) - goto err; - offs = (cnt + 3) + (cmp[cmpptr++] << 4); - memcpy (&org[orgptr], &org[orgptr - offs], cmd); + if(orgptr + cmd > header.size) goto err; + offs = (cnt+3) + (cmp[cmpptr++] << 4); + memcpy(&org[orgptr],&org[orgptr-offs],cmd); orgptr += cmd; break; } } - delete[]cmp; + delete [] cmp; data = (struct mtkdata *) org; // convert to HSC replay data - memset (title, 0, 34); - strncpy (title, data->songname + 1, 33); - memset (composer, 0, 34); - strncpy (composer, data->composername + 1, 33); - memset (instname, 0, 0x80 * 34); - for (i = 0; i < 0x80; i++) - strncpy (instname[i], data->instname[i] + 1, 33); - memcpy (instr, data->insts, 0x80 * 12); - memcpy (song, data->order, 0x80); - memcpy (patterns, data->patterns, header.size - 6084); - for (i = 0; i < 128; i++) - { // correct instruments + memset(title,0,34); strncpy(title,data->songname+1,33); + memset(composer,0,34); strncpy(composer,data->composername+1,33); + memset(instname,0,0x80*34); + for(i=0;i<0x80;i++) + strncpy(instname[i],data->instname[i]+1,33); + memcpy(instr,data->insts,0x80 * 12); + memcpy(song,data->order,0x80); + memcpy(patterns,data->patterns,header.size-6084); + for (i=0;i<128;i++) { // correct instruments instr[i][2] ^= (instr[i][2] & 0x40) << 1; instr[i][3] ^= (instr[i][3] & 0x40) << 1; instr[i][11] >>= 4; // make unsigned } - delete[]org; - rewind (0); + delete [] org; + rewind(0); return true; -err: - delete[]cmp; - delete[]org; + err: + delete [] cmp; + delete [] org; return false; } diff --git a/src/adplug/core/mtk.h b/src/adplug/core/mtk.h index 4d68ac7..b38f916 100644 --- a/src/adplug/core/mtk.h +++ b/src/adplug/core/mtk.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2006 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -26,25 +26,25 @@ class CmtkLoader: public ChscPlayer public: static CPlayer *factory(Copl *newopl); - CmtkLoader(Copl *newopl) - : ChscPlayer(newopl) - { - mtkmode = 1; - }; + CmtkLoader(Copl *newopl) + : ChscPlayer(newopl) + { + mtkmode = 1; + }; - bool load(VFSFile &fd, const CFileProvider &fp); + bool load(const std::string &filename, const CFileProvider &fp); - std::string gettype() - { return std::string("MPU-401 Trakker"); }; - std::string gettitle() - { return std::string(title); }; - std::string getauthor() - { return std::string(composer); }; - unsigned int getinstruments() - { return 128; }; - std::string getinstrument(unsigned int n) - { return std::string(instname[n]); }; + std::string gettype() + { return std::string("MPU-401 Trakker"); }; + std::string gettitle() + { return std::string(title); }; + std::string getauthor() + { return std::string(composer); }; + unsigned int getinstruments() + { return 128; }; + std::string getinstrument(unsigned int n) + { return std::string(instname[n]); }; private: - char title[34],composer[34],instname[0x80][34]; + char title[34],composer[34],instname[0x80][34]; }; diff --git a/src/adplug/core/opl.h b/src/adplug/core/opl.h index b60c1c2..18a26a3 100644 --- a/src/adplug/core/opl.h +++ b/src/adplug/core/opl.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -38,11 +38,11 @@ class Copl { } - virtual void write(int reg, int val) = 0; // combined register select + data write - virtual void setchip(int n) // select OPL chip + virtual void write(int reg, int val) = 0; // combined register select + data write + virtual void setchip(int n) // select OPL chip { if(n < 2) - currChip = n; + currChip = n; } virtual int getchip() // returns current OPL chip @@ -50,7 +50,7 @@ class Copl return currChip; } - virtual void init(void) = 0; // reinitialize OPL chip(s) + virtual void init() = 0; // reinitialize OPL chip(s) // return this OPL chip's type ChipType gettype() @@ -62,8 +62,8 @@ class Copl virtual void update(short *buf, int samples) {} protected: - int currChip; // currently selected OPL chip number - ChipType currType; // this OPL chip's type + int currChip; // currently selected OPL chip number + ChipType currType; // this OPL chip's type }; #endif diff --git a/src/adplug/core/player.cc b/src/adplug/core/player.cc index a70d435..3545a72 100644 --- a/src/adplug/core/player.cc +++ b/src/adplug/core/player.cc @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -25,49 +25,46 @@ /***** CPlayer *****/ -const unsigned short -CPlayer::note_table[12] = - { 363, 385, 408, 432, 458, 485, 514, 544, 577, 611, 647, 686 }; +const unsigned short CPlayer::note_table[12] = + {363, 385, 408, 432, 458, 485, 514, 544, 577, 611, 647, 686}; -const unsigned char -CPlayer::op_table[9] = - { 0x00, 0x01, 0x02, 0x08, 0x09, 0x0a, 0x10, 0x11, 0x12 }; +const unsigned char CPlayer::op_table[9] = + {0x00, 0x01, 0x02, 0x08, 0x09, 0x0a, 0x10, 0x11, 0x12}; -CPlayer::CPlayer (Copl * newopl):opl (newopl), db (CAdPlug::database) +CPlayer::CPlayer(Copl *newopl) + : opl(newopl), db(CAdPlug::database) { } -CPlayer::~CPlayer () +CPlayer::~CPlayer() { } -unsigned long -CPlayer::songlength (int subsong) +unsigned long CPlayer::songlength(int subsong) { - CSilentopl tempopl; - Copl *saveopl = opl; - float slength = 0.0f; + CSilentopl tempopl; + Copl *saveopl = opl; + float slength = 0.0f; // save original OPL from being overwritten opl = &tempopl; // get song length - rewind (subsong); - while (update () && slength < 600000) // song length limit: 10 minutes - slength += 1000.0f / getrefresh (); - rewind (subsong); + rewind(subsong); + while(update() && slength < 600000) // song length limit: 10 minutes + slength += 1000.0f / getrefresh(); + rewind(subsong); // restore original OPL and return opl = saveopl; - return (unsigned long) slength; + return (unsigned long)slength; } -void -CPlayer::seek (unsigned long ms) +void CPlayer::seek(unsigned long ms) { float pos = 0.0f; - rewind (); - while (pos < ms && update ()) // seek to new position - pos += 1000 / getrefresh (); + rewind(); + while(pos < ms && update()) // seek to new position + pos += 1000/getrefresh(); } diff --git a/src/adplug/core/player.h b/src/adplug/core/player.h index 55472e3..4fb05cb 100644 --- a/src/adplug/core/player.h +++ b/src/adplug/core/player.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -32,54 +32,54 @@ class CPlayer { public: CPlayer(Copl *newopl); - virtual ~CPlayer(); + virtual ~CPlayer(); /***** Operational methods *****/ - void seek(unsigned long ms); + void seek(unsigned long ms); - virtual bool load(VFSFile &fd, // loads file - const CFileProvider &fp = CProvider_Filesystem()) = 0; - virtual bool update() = 0; // executes replay code for 1 tick - virtual void rewind(int subsong = -1) = 0; // rewinds to specified subsong - virtual float getrefresh() = 0; // returns needed timer refresh rate + virtual bool load(const std::string &filename, // loads file + const CFileProvider &fp) = 0; + virtual bool update() = 0; // executes replay code for 1 tick + virtual void rewind(int subsong = -1) = 0; // rewinds to specified subsong + virtual float getrefresh() = 0; // returns needed timer refresh rate /***** Informational methods *****/ - unsigned long songlength(int subsong = -1); + unsigned long songlength(int subsong = -1); - virtual std::string gettype() = 0; // returns file type - virtual std::string gettitle() // returns song title - { return std::string(); } - virtual std::string getauthor() // returns song author name - { return std::string(); } - virtual std::string getdesc() // returns song description - { return std::string(); } - virtual unsigned int getpatterns() // returns number of patterns - { return 0; } - virtual unsigned int getpattern() // returns currently playing pattern - { return 0; } - virtual unsigned int getorders() // returns size of orderlist - { return 0; } - virtual unsigned int getorder() // returns currently playing song position - { return 0; } - virtual unsigned int getrow() // returns currently playing row - { return 0; } - virtual unsigned int getspeed() // returns current song speed - { return 0; } - virtual unsigned int getsubsongs() // returns number of subsongs - { return 1; } - virtual unsigned int getsubsong() // returns current subsong - { return 0; } - virtual unsigned int getinstruments() // returns number of instruments - { return 0; } - virtual std::string getinstrument(unsigned int n) // returns n-th instrument name - { return std::string(); } + virtual std::string gettype() = 0; // returns file type + virtual std::string gettitle() // returns song title + { return std::string(); } + virtual std::string getauthor() // returns song author name + { return std::string(); } + virtual std::string getdesc() // returns song description + { return std::string(); } + virtual unsigned int getpatterns() // returns number of patterns + { return 0; } + virtual unsigned int getpattern() // returns currently playing pattern + { return 0; } + virtual unsigned int getorders() // returns size of orderlist + { return 0; } + virtual unsigned int getorder() // returns currently playing song position + { return 0; } + virtual unsigned int getrow() // returns currently playing row + { return 0; } + virtual unsigned int getspeed() // returns current song speed + { return 0; } + virtual unsigned int getsubsongs() // returns number of subsongs + { return 1; } + virtual unsigned int getsubsong() // returns current subsong + { return 0; } + virtual unsigned int getinstruments() // returns number of instruments + { return 0; } + virtual std::string getinstrument(unsigned int n) // returns n-th instrument name + { return std::string(); } protected: - Copl *opl; // our OPL chip - CAdPlugDatabase *db; // AdPlug Database + Copl *opl; // our OPL chip + CAdPlugDatabase *db; // AdPlug Database - static const unsigned short note_table[12]; // standard adlib note table - static const unsigned char op_table[9]; // the 9 operators as expected by the OPL + static const unsigned short note_table[12]; // standard adlib note table + static const unsigned char op_table[9]; // the 9 operators as expected by the OPL }; #endif diff --git a/src/adplug/core/players.cc b/src/adplug/core/players.cc index 5553b77..f15c5c3 100644 --- a/src/adplug/core/players.cc +++ b/src/adplug/core/players.cc @@ -24,8 +24,6 @@ #include "players.h" -#include <libaudcore/audstrings.h> - /***** CPlayerDesc *****/ CPlayerDesc::CPlayerDesc() @@ -50,7 +48,7 @@ CPlayerDesc::CPlayerDesc(Factory f, const std::string &type, const char *ext) // Determine length of passed extensions list while(*i) i += strlen(i) + 1; - extlength = i - ext + 1; // length = difference between last and first char + 1 + extlength = i - ext + 1; // length = difference between last and first char + 1 extensions = (char *)malloc(extlength); memcpy(extensions, ext, extlength); @@ -73,8 +71,8 @@ void CPlayerDesc::add_extension(const char *ext) const char *CPlayerDesc::get_extension(unsigned int n) const { - const char *i = extensions; - unsigned int j; + const char *i = extensions; + unsigned int j; for(j = 0; j < n && (*i); j++, i += strlen(i) + 1) ; return (*i != '\0' ? i : 0); @@ -84,7 +82,7 @@ const char *CPlayerDesc::get_extension(unsigned int n) const const CPlayerDesc *CPlayers::lookup_filetype(const std::string &ftype) const { - const_iterator i; + const_iterator i; for(i = begin(); i != end(); i++) if((*i)->filetype == ftype) @@ -95,13 +93,13 @@ const CPlayerDesc *CPlayers::lookup_filetype(const std::string &ftype) const const CPlayerDesc *CPlayers::lookup_extension(const std::string &extension) const { - const_iterator i; - unsigned int j; + const_iterator i; + unsigned int j; for(i = begin(); i != end(); i++) for(j = 0; (*i)->get_extension(j); j++) - if(!strcmp_nocase(extension.c_str(), (*i)->get_extension(j))) - return *i; + if(!strcasecmp(extension.c_str(), (*i)->get_extension(j))) + return *i; return 0; } diff --git a/src/adplug/core/players.h b/src/adplug/core/players.h index 6e2633e..686c20b 100644 --- a/src/adplug/core/players.h +++ b/src/adplug/core/players.h @@ -1,17 +1,17 @@ /* * AdPlug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -33,8 +33,8 @@ class CPlayerDesc public: typedef CPlayer *(*Factory)(Copl *); - Factory factory; - std::string filetype; + Factory factory; + std::string filetype; CPlayerDesc(); CPlayerDesc(const CPlayerDesc &pd); @@ -46,8 +46,8 @@ public: const char *get_extension(unsigned int n) const; private: - char *extensions; - unsigned long extlength; + char *extensions; + unsigned long extlength; }; class CPlayers: public std::list<const CPlayerDesc *> diff --git a/src/adplug/core/protrack.cc b/src/adplug/core/protrack.cc index ba43cae..1b038ae 100644 --- a/src/adplug/core/protrack.cc +++ b/src/adplug/core/protrack.cc @@ -25,494 +25,409 @@ * Protracker-like format, this is most certainly the player you want to use. */ -#include <string.h> - +#include <cstring> #include "protrack.h" #include "debug.h" -#define SPECIALARPLEN 256 // Standard length of special arpeggio lists -#define JUMPMARKER 0x80 // Orderlist jump marker +#define SPECIALARPLEN 256 // Standard length of special arpeggio lists +#define JUMPMARKER 0x80 // Orderlist jump marker // SA2 compatible adlib note table -const unsigned short -CmodPlayer::sa2_notetable[12] = - { 340, 363, 385, 408, 432, 458, 485, 514, 544, 577, 611, 647 }; +const unsigned short CmodPlayer::sa2_notetable[12] = + {340,363,385,408,432,458,485,514,544,577,611,647}; // SA2 compatible vibrato rate table -const unsigned char -CmodPlayer::vibratotab[32] = - { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 16, 15, 14, 13, -12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; +const unsigned char CmodPlayer::vibratotab[32] = + {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1}; /*** public methods *************************************/ -CmodPlayer::CmodPlayer (Copl * newopl):CPlayer (newopl), inst (0), order (0), arplist (0), arpcmd (0), initspeed (6), -nop (0), activechan (0xffffffff), flags (Standard), curchip (opl->getchip ()), -nrows (0), npats (0), nchans (0) +CmodPlayer::CmodPlayer(Copl *newopl) + : CPlayer(newopl), inst(0), order(0), arplist(0), arpcmd(0), initspeed(6), + nop(0), activechan(0xffffffff), flags(Standard), curchip(opl->getchip()), + nrows(0), npats(0), nchans(0) { - realloc_order (128); - realloc_patterns (64, 64, 9); - realloc_instruments (250); - init_notetable (sa2_notetable); + realloc_order(128); + realloc_patterns(64, 64, 9); + realloc_instruments(250); + init_notetable(sa2_notetable); } -CmodPlayer::~CmodPlayer () +CmodPlayer::~CmodPlayer() { - dealloc (); + dealloc(); } -bool -CmodPlayer::update () +bool CmodPlayer::update() { - unsigned char pattbreak = 0, donote, pattnr, chan, oplchan, info1, + unsigned char pattbreak=0, donote, pattnr, chan, oplchan, info1, info2, info, pattern_delay; - unsigned short track; - unsigned long row; + unsigned short track; + unsigned long row; - if (!speed) // song full stop + if(!speed) // song full stop return !songend; // effect handling (timer dependant) - for (chan = 0; chan < nchans; chan++) - { - oplchan = set_opl_chip (chan); + for(chan = 0; chan < nchans; chan++) { + oplchan = set_opl_chip(chan); - if (arplist && arpcmd && inst[channel[chan].inst].arpstart) // special arpeggio - { - if (channel[chan].arpspdcnt) + if(arplist && arpcmd && inst[channel[chan].inst].arpstart) { // special arpeggio + if(channel[chan].arpspdcnt) channel[chan].arpspdcnt--; - else if (arpcmd[channel[chan].arppos] != 255) - { - switch (arpcmd[channel[chan].arppos]) - { - case 252: - channel[chan].vol1 = arplist[channel[chan].arppos]; // set volume - if (channel[chan].vol1 > 63) // ????? - channel[chan].vol1 = 63; - channel[chan].vol2 = channel[chan].vol1; - setvolume (chan); - break; - case 253: - channel[chan].key = 0; - setfreq (chan); - break; // release sustaining note - case 254: - channel[chan].arppos = arplist[channel[chan].arppos]; - break; // arpeggio loop - default: - if (arpcmd[channel[chan].arppos]) - { - if (arpcmd[channel[chan].arppos] / 10) - opl->write (0xe3 + op_table[oplchan], - arpcmd[channel[chan].arppos] / 10 - 1); - if (arpcmd[channel[chan].arppos] % 10) - opl->write (0xe0 + op_table[oplchan], - (arpcmd[channel[chan].arppos] % 10) - 1); - if (arpcmd[channel[chan].arppos] < 10) // ????? - opl->write (0xe0 + op_table[oplchan], - arpcmd[channel[chan].arppos] - 1); + else + if(arpcmd[channel[chan].arppos] != 255) { + switch(arpcmd[channel[chan].arppos]) { + case 252: channel[chan].vol1 = arplist[channel[chan].arppos]; // set volume + if(channel[chan].vol1 > 63) // ????? + channel[chan].vol1 = 63; + channel[chan].vol2 = channel[chan].vol1; + setvolume(chan); + break; + case 253: channel[chan].key = 0; setfreq(chan); break; // release sustaining note + case 254: channel[chan].arppos = arplist[channel[chan].arppos]; break; // arpeggio loop + default: if(arpcmd[channel[chan].arppos]) { + if(arpcmd[channel[chan].arppos] / 10) + opl->write(0xe3 + op_table[oplchan], arpcmd[channel[chan].arppos] / 10 - 1); + if(arpcmd[channel[chan].arppos] % 10) + opl->write(0xe0 + op_table[oplchan], (arpcmd[channel[chan].arppos] % 10) - 1); + if(arpcmd[channel[chan].arppos] < 10) // ????? + opl->write(0xe0 + op_table[oplchan], arpcmd[channel[chan].arppos] - 1); } + } + if(arpcmd[channel[chan].arppos] != 252) { + if(arplist[channel[chan].arppos] <= 96) + setnote(chan,channel[chan].note + arplist[channel[chan].arppos]); + if(arplist[channel[chan].arppos] >= 100) + setnote(chan,arplist[channel[chan].arppos] - 100); + } else + setnote(chan,channel[chan].note); + setfreq(chan); + if(arpcmd[channel[chan].arppos] != 255) + channel[chan].arppos++; + channel[chan].arpspdcnt = inst[channel[chan].inst].arpspeed - 1; } - if (arpcmd[channel[chan].arppos] != 252) - { - if (arplist[channel[chan].arppos] <= 96) - setnote (chan, - channel[chan].note + arplist[channel[chan].arppos]); - if (arplist[channel[chan].arppos] >= 100) - setnote (chan, arplist[channel[chan].arppos] - 100); - } - else - setnote (chan, channel[chan].note); - setfreq (chan); - if (arpcmd[channel[chan].arppos] != 255) - channel[chan].arppos++; - channel[chan].arpspdcnt = inst[channel[chan].inst].arpspeed - 1; - } } info1 = channel[chan].info1; info2 = channel[chan].info2; - if (flags & Decimal) + if(flags & Decimal) info = channel[chan].info1 * 10 + channel[chan].info2; else info = (channel[chan].info1 << 4) + channel[chan].info2; - switch (channel[chan].fx) - { - case 0: - if (info) - { // arpeggio - if (channel[chan].trigger < 2) - channel[chan].trigger++; - else - channel[chan].trigger = 0; - switch (channel[chan].trigger) - { - case 0: - setnote (chan, channel[chan].note); - break; - case 1: - setnote (chan, channel[chan].note + info1); - break; - case 2: - setnote (chan, channel[chan].note + info2); - } - setfreq (chan); + switch(channel[chan].fx) { + case 0: if(info) { // arpeggio + if(channel[chan].trigger < 2) + channel[chan].trigger++; + else + channel[chan].trigger = 0; + switch(channel[chan].trigger) { + case 0: setnote(chan,channel[chan].note); break; + case 1: setnote(chan,channel[chan].note + info1); break; + case 2: setnote(chan,channel[chan].note + info2); } + setfreq(chan); + } break; - case 1: - slide_up (chan, info); - setfreq (chan); - break; // slide up - case 2: - slide_down (chan, info); - setfreq (chan); - break; // slide down - case 3: - tone_portamento (chan, channel[chan].portainfo); - break; // tone portamento - case 4: - vibrato (chan, channel[chan].vibinfo1, channel[chan].vibinfo2); - break; // vibrato - case 5: // tone portamento & volume slide - case 6: - if (channel[chan].fx == 5) // vibrato & volume slide - tone_portamento (chan, channel[chan].portainfo); - else - vibrato (chan, channel[chan].vibinfo1, channel[chan].vibinfo2); - case 10: - if (del % 4) // SA2 volume slide - break; - if (info1) - vol_up (chan, info1); + case 1: slide_up(chan,info); setfreq(chan); break; // slide up + case 2: slide_down(chan,info); setfreq(chan); break; // slide down + case 3: tone_portamento(chan,channel[chan].portainfo); break; // tone portamento + case 4: vibrato(chan,channel[chan].vibinfo1,channel[chan].vibinfo2); break; // vibrato + case 5: // tone portamento & volume slide + case 6: if(channel[chan].fx == 5) // vibrato & volume slide + tone_portamento(chan,channel[chan].portainfo); + else + vibrato(chan,channel[chan].vibinfo1,channel[chan].vibinfo2); + case 10: if(del % 4) // SA2 volume slide + break; + if(info1) + vol_up(chan,info1); else - vol_down (chan, info2); - setvolume (chan); + vol_down(chan,info2); + setvolume(chan); break; - case 14: - if (info1 == 3) // retrig note - if (!(del % (info2 + 1))) - playnote (chan); + case 14: if(info1 == 3) // retrig note + if(!(del % (info2+1))) + playnote(chan); break; - case 16: - if (del % 4) // AMD volume slide - break; - if (info1) - vol_up_alt (chan, info1); + case 16: if(del % 4) // AMD volume slide + break; + if(info1) + vol_up_alt(chan,info1); else - vol_down_alt (chan, info2); - setvolume (chan); + vol_down_alt(chan,info2); + setvolume(chan); break; - case 20: // RAD volume slide - if (info < 50) - vol_down_alt (chan, info); + case 20: // RAD volume slide + if(info < 50) + vol_down_alt(chan,info); else - vol_up_alt (chan, info - 50); - setvolume (chan); + vol_up_alt(chan,info - 50); + setvolume(chan); break; - case 26: // volume slide - if (info1) - vol_up (chan, info1); + case 26: // volume slide + if(info1) + vol_up(chan,info1); else - vol_down (chan, info2); - setvolume (chan); + vol_down(chan,info2); + setvolume(chan); break; case 28: - if (info1) - { - slide_up (chan, 1); - channel[chan].info1--; + if (info1) { + slide_up(chan,1); channel[chan].info1--; } - if (info2) - { - slide_down (chan, 1); - channel[chan].info2--; + if (info2) { + slide_down(chan,1); channel[chan].info2--; } - setfreq (chan); + setfreq(chan); break; } } - if (del) - { // speed compensation + if(del) { // speed compensation del--; return !songend; } // arrangement handling - if (!resolve_order ()) - return !songend; + if(!resolve_order()) return !songend; pattnr = order[ord]; - if (!rw) - AdPlug_LogWrite ("\nCmodPlayer::update(): Pattern: %d, Order: %d\n", - pattnr, ord); - AdPlug_LogWrite ("CmodPlayer::update():%3d|", rw); + if(!rw) AdPlug_LogWrite("\nCmodPlayer::update(): Pattern: %d, Order: %d\n", pattnr, ord); + AdPlug_LogWrite("CmodPlayer::update():%3d|", rw); // play row pattern_delay = 0; row = rw; - for (chan = 0; chan < nchans; chan++) - { - oplchan = set_opl_chip (chan); + for(chan = 0; chan < nchans; chan++) { + oplchan = set_opl_chip(chan); - if (!(activechan >> (31 - chan)) & 1) - { // channel active? - AdPlug_LogWrite ("N/A|"); + if(!(activechan >> (31 - chan)) & 1) { // channel active? + AdPlug_LogWrite("N/A|"); continue; } - if (!(track = trackord[pattnr][chan])) - { // resolve track - AdPlug_LogWrite ("------------|"); + if(!(track = trackord[pattnr][chan])) { // resolve track + AdPlug_LogWrite("------------|"); continue; - } - else + } else track--; - if (track >= npats*nchans) { // prevent overflow - songend = 1; - return !songend; - } - AdPlug_LogWrite ("%3d%3d%2X%2X%2X|", tracks[track][row].note, - tracks[track][row].inst, tracks[track][row].command, - tracks[track][row].param1, tracks[track][row].param2); + AdPlug_LogWrite("%3d%3d%2X%2X%2X|", tracks[track][row].note, + tracks[track][row].inst, tracks[track][row].command, + tracks[track][row].param1, tracks[track][row].param2); donote = 0; - if (tracks[track][row].inst) - { + if(tracks[track][row].inst) { channel[chan].inst = tracks[track][row].inst - 1; - if (!(flags & Faust)) - { + if (!(flags & Faust)) { channel[chan].vol1 = 63 - (inst[channel[chan].inst].data[10] & 63); channel[chan].vol2 = 63 - (inst[channel[chan].inst].data[9] & 63); - setvolume (chan); + setvolume(chan); } } - if (tracks[track][row].note && tracks[track][row].command != 3) - { // no tone portamento + if(tracks[track][row].note && tracks[track][row].command != 3) { // no tone portamento channel[chan].note = tracks[track][row].note; - setnote (chan, tracks[track][row].note); + setnote(chan,tracks[track][row].note); channel[chan].nextfreq = channel[chan].freq; channel[chan].nextoct = channel[chan].oct; channel[chan].arppos = inst[channel[chan].inst].arpstart; channel[chan].arpspdcnt = 0; - if (tracks[track][row].note != 127) // handle key off + if(tracks[track][row].note != 127) // handle key off donote = 1; } channel[chan].fx = tracks[track][row].command; channel[chan].info1 = tracks[track][row].param1; channel[chan].info2 = tracks[track][row].param2; - if (donote) - playnote (chan); + if(donote) + playnote(chan); // command handling (row dependant) info1 = channel[chan].info1; info2 = channel[chan].info2; - if (flags & Decimal) + if(flags & Decimal) info = channel[chan].info1 * 10 + channel[chan].info2; else info = (channel[chan].info1 << 4) + channel[chan].info2; - switch (channel[chan].fx) - { - case 3: // tone portamento - if (tracks[track][row].note) - { - if (tracks[track][row].note < 13) + switch(channel[chan].fx) { + case 3: // tone portamento + if(tracks[track][row].note) { + if(tracks[track][row].note < 13) channel[chan].nextfreq = notetable[tracks[track][row].note - 1]; - else if (tracks[track][row].note % 12 > 0) - channel[chan].nextfreq = - notetable[(tracks[track][row].note % 12) - 1]; else - channel[chan].nextfreq = notetable[11]; + if(tracks[track][row].note % 12 > 0) + channel[chan].nextfreq = notetable[(tracks[track][row].note % 12) - 1]; + else + channel[chan].nextfreq = notetable[11]; channel[chan].nextoct = (tracks[track][row].note - 1) / 12; - if (tracks[track][row].note == 127) - { // handle key off + if(tracks[track][row].note == 127) { // handle key off channel[chan].nextfreq = channel[chan].freq; channel[chan].nextoct = channel[chan].oct; } } - if (info) // remember vars + if(info) // remember vars channel[chan].portainfo = info; break; - case 4: // vibrato (remember vars) - if (info) - { + case 4: // vibrato (remember vars) + if(info) { channel[chan].vibinfo1 = info1; channel[chan].vibinfo2 = info2; } break; - case 7: - tempo = info; - break; // set tempo + case 7: tempo = info; break; // set tempo - case 8: - channel[chan].key = 0; - setfreq (chan); - break; // release sustaining note + case 8: channel[chan].key = 0; setfreq(chan); break; // release sustaining note - case 9: // set carrier/modulator volume - if (info1) + case 9: // set carrier/modulator volume + if(info1) channel[chan].vol1 = info1 * 7; else channel[chan].vol2 = info2 * 7; - setvolume (chan); + setvolume(chan); break; - case 11: // position jump - pattbreak = 1; - rw = 0; - if (info < ord) - songend = 1; - ord = info; - break; + case 11: // position jump + pattbreak = 1; rw = 0; if(info < ord) songend = 1; ord = info; break; - case 12: // set volume + case 12: // set volume channel[chan].vol1 = info; channel[chan].vol2 = info; - if (channel[chan].vol1 > 63) + if(channel[chan].vol1 > 63) channel[chan].vol1 = 63; - if (channel[chan].vol2 > 63) + if(channel[chan].vol2 > 63) channel[chan].vol2 = 63; - setvolume (chan); + setvolume(chan); break; - case 13: // pattern break - if (!pattbreak) - { - pattbreak = 1; - rw = info; - ord++; - } - break; + case 13: // pattern break + if(!pattbreak) { pattbreak = 1; rw = info; ord++; } break; - case 14: // extended command - switch (info1) - { - case 0: // define cell-tremolo - if (info2) + case 14: // extended command + switch(info1) { + case 0: // define cell-tremolo + if(info2) regbd |= 128; else regbd &= 127; - opl->write (0xbd, regbd); + opl->write(0xbd,regbd); break; - case 1: // define cell-vibrato - if (info2) + case 1: // define cell-vibrato + if(info2) regbd |= 64; else regbd &= 191; - opl->write (0xbd, regbd); + opl->write(0xbd,regbd); break; - case 4: // increase volume fine - vol_up_alt (chan, info2); - setvolume (chan); + case 4: // increase volume fine + vol_up_alt(chan,info2); + setvolume(chan); break; - case 5: // decrease volume fine - vol_down_alt (chan, info2); - setvolume (chan); + case 5: // decrease volume fine + vol_down_alt(chan,info2); + setvolume(chan); break; - case 6: // manual slide up - slide_up (chan, info2); - setfreq (chan); + case 6: // manual slide up + slide_up(chan,info2); + setfreq(chan); break; - case 7: // manual slide down - slide_down (chan, info2); - setfreq (chan); + case 7: // manual slide down + slide_down(chan,info2); + setfreq(chan); break; - case 8: // pattern delay (rows) + case 8: // pattern delay (rows) pattern_delay = info2 * speed; break; } break; - case 15: // SA2 set speed - if (info <= 0x1f) + case 15: // SA2 set speed + if(info <= 0x1f) speed = info; - if (info >= 0x32) + if(info >= 0x32) tempo = info; - if (!info) + if(!info) songend = 1; break; - case 17: // alternate set volume + case 17: // alternate set volume channel[chan].vol1 = info; - if (channel[chan].vol1 > 63) + if(channel[chan].vol1 > 63) channel[chan].vol1 = 63; - if (inst[channel[chan].inst].data[0] & 1) - { + if(inst[channel[chan].inst].data[0] & 1) { channel[chan].vol2 = info; - if (channel[chan].vol2 > 63) + if(channel[chan].vol2 > 63) channel[chan].vol2 = 63; } - setvolume (chan); + setvolume(chan); break; - case 18: // AMD set speed - if (info <= 31 && info > 0) + case 18: // AMD set speed + if(info <= 31 && info > 0) speed = info; - if (info > 31 || !info) + if(info > 31 || !info) tempo = info; break; - case 19: // RAD/A2M set speed + case 19: // RAD/A2M set speed speed = (info ? info : info + 1); break; - case 21: // set modulator volume - if (info <= 63) + case 21: // set modulator volume + if(info <= 63) channel[chan].vol2 = info; else channel[chan].vol2 = 63; - setvolume (chan); + setvolume(chan); break; - case 22: // set carrier volume - if (info <= 63) + case 22: // set carrier volume + if(info <= 63) channel[chan].vol1 = info; else channel[chan].vol1 = 63; - setvolume (chan); + setvolume(chan); break; - case 23: // fine frequency slide up - slide_up (chan, info); - setfreq (chan); + case 23: // fine frequency slide up + slide_up(chan,info); + setfreq(chan); break; - case 24: // fine frequency slide down - slide_down (chan, info); - setfreq (chan); + case 24: // fine frequency slide down + slide_down(chan,info); + setfreq(chan); break; - case 25: // set carrier/modulator waveform - if (info1 != 0x0f) - opl->write (0xe3 + op_table[oplchan], info1); - if (info2 != 0x0f) - opl->write (0xe0 + op_table[oplchan], info2); + case 25: // set carrier/modulator waveform + if(info1 != 0x0f) + opl->write(0xe3 + op_table[oplchan],info1); + if(info2 != 0x0f) + opl->write(0xe0 + op_table[oplchan],info2); break; - case 27: // set chip tremolo/vibrato - if (info1) + case 27: // set chip tremolo/vibrato + if(info1) regbd |= 128; else regbd &= 127; - if (info2) + if(info2) regbd |= 64; else regbd &= 191; - opl->write (0xbd, regbd); + opl->write(0xbd,regbd); break; - case 29: // pattern delay (frames) + case 29: // pattern delay (frames) pattern_delay = info; break; } @@ -521,23 +436,20 @@ CmodPlayer::update () // speed compensation del = speed - 1 + pattern_delay; - if (!pattbreak) - { // next row (only if no manual advance) + if(!pattbreak) { // next row (only if no manual advance) rw++; - if (rw >= nrows) - { + if(rw >= nrows) { rw = 0; ord++; } } - resolve_order (); // so we can report songend right away - AdPlug_LogWrite ("\n"); + resolve_order(); // so we can report songend right away + AdPlug_LogWrite("\n"); return !songend; } -unsigned char -CmodPlayer::set_opl_chip (unsigned char chan) +unsigned char CmodPlayer::set_opl_chip(unsigned char chan) /* * Sets OPL chip according to channel number. Channels 0-8 are on first chip, * channels 9-17 are on second chip. Returns corresponding OPL channel @@ -546,17 +458,15 @@ CmodPlayer::set_opl_chip (unsigned char chan) { int newchip = chan < 9 ? 0 : 1; - if (newchip != curchip) - { - opl->setchip (newchip); + if(newchip != curchip) { + opl->setchip(newchip); curchip = newchip; } return chan % 9; } -bool -CmodPlayer::resolve_order () +bool CmodPlayer::resolve_order() /* * Resolves current orderlist entry, checking for jumps and loops. * @@ -564,21 +474,15 @@ CmodPlayer::resolve_order () * has been detected. */ { - if (ord < length) - { - while (order[ord] >= JUMPMARKER) - { // jump to order + if(ord < length) { + while(order[ord] >= JUMPMARKER) { // jump to order unsigned long neword = order[ord] - JUMPMARKER; - if (neword <= ord) - songend = 1; - if (neword == ord) - return false; + if(neword <= ord) songend = 1; + if(neword == ord) return false; ord = neword; } - } - else - { + } else { songend = 1; ord = restartpos; } @@ -586,62 +490,53 @@ CmodPlayer::resolve_order () return true; } -void -CmodPlayer::rewind (int subsong) +void CmodPlayer::rewind(int subsong) { unsigned long i; // Reset playing variables songend = del = ord = rw = regbd = 0; - tempo = bpm; - speed = initspeed; + tempo = bpm; speed = initspeed; // Reset channel data - memset (channel, 0, sizeof (Channel) * nchans); + memset(channel,0,sizeof(Channel)*nchans); // Compute number of patterns, if needed - if (!nop) - for (i = 0; i < length; i++) + if(!nop) + for(i=0;i<length;i++) nop = (order[i] > nop ? order[i] : nop); - opl->init (); // Reset OPL chip - opl->write (1, 32); // Go to ym3812 mode + opl->init(); // Reset OPL chip + opl->write(1, 32); // Go to ym3812 mode // Enable OPL3 extensions if flagged - if (flags & Opl3) - { - opl->setchip (1); - opl->write (1, 32); - opl->write (5, 1); - opl->setchip (0); + if(flags & Opl3) { + opl->setchip(1); + opl->write(1, 32); + opl->write(5, 1); + opl->setchip(0); } // Enable tremolo/vibrato depth if flagged - if (flags & Tremolo) - regbd |= 128; - if (flags & Vibrato) - regbd |= 64; - if (regbd) - opl->write (0xbd, regbd); + if(flags & Tremolo) regbd |= 128; + if(flags & Vibrato) regbd |= 64; + if(regbd) opl->write(0xbd, regbd); } -float -CmodPlayer::getrefresh () +float CmodPlayer::getrefresh() { return (float) (tempo / 2.5); } -void -CmodPlayer::init_trackord () +void CmodPlayer::init_trackord() { unsigned long i; - for (i = 0; i < npats * nchans; i++) + for(i=0;i<npats*nchans;i++) trackord[i / nchans][i % nchans] = i + 1; } -bool -CmodPlayer::init_specialarp () +bool CmodPlayer::init_specialarp() { arplist = new unsigned char[SPECIALARPLEN]; arpcmd = new unsigned char[SPECIALARPLEN]; @@ -649,346 +544,281 @@ CmodPlayer::init_specialarp () return true; } -void -CmodPlayer::init_notetable (const unsigned short *newnotetable) +void CmodPlayer::init_notetable(const unsigned short *newnotetable) { - memcpy (notetable, newnotetable, 12 * 2); + memcpy(notetable, newnotetable, 12 * 2); } -bool -CmodPlayer::realloc_order (unsigned long len) +bool CmodPlayer::realloc_order(unsigned long len) { - if (order) - delete[]order; + if(order) delete [] order; order = new unsigned char[len]; return true; } -bool -CmodPlayer::realloc_patterns (unsigned long pats, unsigned long rows, - unsigned long chans) +bool CmodPlayer::realloc_patterns(unsigned long pats, unsigned long rows, unsigned long chans) { unsigned long i; - dealloc_patterns (); + dealloc_patterns(); // set new number of tracks, rows and channels - npats = pats; - nrows = rows; - nchans = chans; + npats = pats; nrows = rows; nchans = chans; // alloc new patterns tracks = new Tracks *[pats * chans]; - for (i = 0; i < pats * chans; i++) - tracks[i] = new Tracks[rows]; + for(i=0;i<pats*chans;i++) tracks[i] = new Tracks[rows]; trackord = new unsigned short *[pats]; - for (i = 0; i < pats; i++) - trackord[i] = new unsigned short[chans]; + for(i=0;i<pats;i++) trackord[i] = new unsigned short[chans]; channel = new Channel[chans]; // initialize new patterns - for (i = 0; i < pats * chans; i++) - memset (tracks[i], 0, sizeof (Tracks) * rows); - for (i = 0; i < pats; i++) - memset (trackord[i], 0, chans * 2); + for(i=0;i<pats*chans;i++) memset(tracks[i],0,sizeof(Tracks)*rows); + for(i=0;i<pats;i++) memset(trackord[i],0,chans*2); return true; } -void -CmodPlayer::dealloc_patterns () +void CmodPlayer::dealloc_patterns() { unsigned long i; // dealloc everything previously allocated - if (npats && nrows && nchans) - { - for (i = 0; i < npats * nchans; i++) - delete[]tracks[i]; - delete[]tracks; - for (i = 0; i < npats; i++) - delete[]trackord[i]; - delete[]trackord; - delete[]channel; + if(npats && nrows && nchans) { + for(i=0;i<npats*nchans;i++) delete [] tracks[i]; + delete [] tracks; + for(i=0;i<npats;i++) delete [] trackord[i]; + delete [] trackord; + delete [] channel; } } -bool -CmodPlayer::realloc_instruments (unsigned long len) +bool CmodPlayer::realloc_instruments(unsigned long len) { // dealloc previous instance, if any - if (inst) - delete[]inst; + if(inst) delete [] inst; inst = new Instrument[len]; - memset (inst, 0, sizeof (Instrument) * len); // reset instruments + memset(inst,0,sizeof(Instrument)*len); // reset instruments return true; } -void -CmodPlayer::dealloc () +void CmodPlayer::dealloc() { - if (inst) - delete[]inst; - if (order) - delete[]order; - if (arplist) - delete[]arplist; - if (arpcmd) - delete[]arpcmd; - dealloc_patterns (); + if(inst) delete [] inst; + if(order) delete [] order; + if(arplist) delete [] arplist; + if(arpcmd) delete [] arpcmd; + dealloc_patterns(); } /*** private methods *************************************/ -void -CmodPlayer::setvolume (unsigned char chan) +void CmodPlayer::setvolume(unsigned char chan) { - unsigned char oplchan = set_opl_chip (chan); + unsigned char oplchan = set_opl_chip(chan); - if (flags & Faust) - setvolume_alt (chan); - else - { - opl->write (0x40 + op_table[oplchan], - 63 - channel[chan].vol2 + - (inst[channel[chan].inst].data[9] & 192)); - opl->write (0x43 + op_table[oplchan], - 63 - channel[chan].vol1 + - (inst[channel[chan].inst].data[10] & 192)); + if(flags & Faust) + setvolume_alt(chan); + else { + opl->write(0x40 + op_table[oplchan], 63-channel[chan].vol2 + (inst[channel[chan].inst].data[9] & 192)); + opl->write(0x43 + op_table[oplchan], 63-channel[chan].vol1 + (inst[channel[chan].inst].data[10] & 192)); } } -void -CmodPlayer::setvolume_alt (unsigned char chan) +void CmodPlayer::setvolume_alt(unsigned char chan) { - unsigned char oplchan = set_opl_chip (chan); + unsigned char oplchan = set_opl_chip(chan); unsigned char ivol2 = inst[channel[chan].inst].data[9] & 63; unsigned char ivol1 = inst[channel[chan].inst].data[10] & 63; - opl->write (0x40 + op_table[oplchan], - (((63 - (channel[chan].vol2 & 63)) + ivol2) >> 1) + - (inst[channel[chan].inst].data[9] & 192)); - opl->write (0x43 + op_table[oplchan], - (((63 - (channel[chan].vol1 & 63)) + ivol1) >> 1) + - (inst[channel[chan].inst].data[10] & 192)); + opl->write(0x40 + op_table[oplchan], (((63 - (channel[chan].vol2 & 63)) + ivol2) >> 1) + (inst[channel[chan].inst].data[9] & 192)); + opl->write(0x43 + op_table[oplchan], (((63 - (channel[chan].vol1 & 63)) + ivol1) >> 1) + (inst[channel[chan].inst].data[10] & 192)); } -void -CmodPlayer::setfreq (unsigned char chan) +void CmodPlayer::setfreq(unsigned char chan) { - unsigned char oplchan = set_opl_chip (chan); + unsigned char oplchan = set_opl_chip(chan); - opl->write (0xa0 + oplchan, channel[chan].freq & 255); - if (channel[chan].key) - opl->write (0xb0 + oplchan, - ((channel[chan].freq & 768) >> 8) + - ((channel[chan].oct << 2) | 32)); + opl->write(0xa0 + oplchan, channel[chan].freq & 255); + if(channel[chan].key) + opl->write(0xb0 + oplchan, ((channel[chan].freq & 768) >> 8) + ((channel[chan].oct << 2) | 32)); else - opl->write (0xb0 + oplchan, - ((channel[chan].freq & 768) >> 8) + (channel[chan].oct << 2)); + opl->write(0xb0 + oplchan, ((channel[chan].freq & 768) >> 8) + (channel[chan].oct << 2)); } -void -CmodPlayer::playnote (unsigned char chan) +void CmodPlayer::playnote(unsigned char chan) { - unsigned char oplchan = set_opl_chip (chan); + unsigned char oplchan = set_opl_chip(chan); unsigned char op = op_table[oplchan], insnr = channel[chan].inst; - if (!(flags & NoKeyOn)) - opl->write (0xb0 + oplchan, 0); // stop old note + if(!(flags & NoKeyOn)) + opl->write(0xb0 + oplchan, 0); // stop old note // set instrument data - opl->write (0x20 + op, inst[insnr].data[1]); - opl->write (0x23 + op, inst[insnr].data[2]); - opl->write (0x60 + op, inst[insnr].data[3]); - opl->write (0x63 + op, inst[insnr].data[4]); - opl->write (0x80 + op, inst[insnr].data[5]); - opl->write (0x83 + op, inst[insnr].data[6]); - opl->write (0xe0 + op, inst[insnr].data[7]); - opl->write (0xe3 + op, inst[insnr].data[8]); - opl->write (0xc0 + oplchan, inst[insnr].data[0]); - opl->write (0xbd, inst[insnr].misc); // set misc. register + opl->write(0x20 + op, inst[insnr].data[1]); + opl->write(0x23 + op, inst[insnr].data[2]); + opl->write(0x60 + op, inst[insnr].data[3]); + opl->write(0x63 + op, inst[insnr].data[4]); + opl->write(0x80 + op, inst[insnr].data[5]); + opl->write(0x83 + op, inst[insnr].data[6]); + opl->write(0xe0 + op, inst[insnr].data[7]); + opl->write(0xe3 + op, inst[insnr].data[8]); + opl->write(0xc0 + oplchan, inst[insnr].data[0]); + opl->write(0xbd, inst[insnr].misc); // set misc. register // set frequency, volume & play channel[chan].key = 1; - setfreq (chan); + setfreq(chan); - if (flags & Faust) - { + if (flags & Faust) { channel[chan].vol2 = 63; channel[chan].vol1 = 63; } - setvolume (chan); + setvolume(chan); } -void -CmodPlayer::setnote (unsigned char chan, int note) +void CmodPlayer::setnote(unsigned char chan, int note) { - if (note > 96) - { - if (note == 127) - { // key off + if(note > 96) { + if(note == 127) { // key off channel[chan].key = 0; - setfreq (chan); + setfreq(chan); return; - } - else + } else note = 96; } - if (note < 13) + if(note < 13) channel[chan].freq = notetable[note - 1]; - else if (note % 12 > 0) - channel[chan].freq = notetable[(note % 12) - 1]; else - channel[chan].freq = notetable[11]; + if(note % 12 > 0) + channel[chan].freq = notetable[(note % 12) - 1]; + else + channel[chan].freq = notetable[11]; channel[chan].oct = (note - 1) / 12; channel[chan].freq += inst[channel[chan].inst].slide; // apply pre-slide } -void -CmodPlayer::slide_down (unsigned char chan, int amount) +void CmodPlayer::slide_down(unsigned char chan, int amount) { channel[chan].freq -= amount; - if (channel[chan].freq <= 342) - { - if (channel[chan].oct) - { + if(channel[chan].freq <= 342) { + if(channel[chan].oct) { channel[chan].oct--; channel[chan].freq <<= 1; - } - else + } else channel[chan].freq = 342; } } -void -CmodPlayer::slide_up (unsigned char chan, int amount) +void CmodPlayer::slide_up(unsigned char chan, int amount) { channel[chan].freq += amount; - if (channel[chan].freq >= 686) - { - if (channel[chan].oct < 7) - { + if(channel[chan].freq >= 686) { + if(channel[chan].oct < 7) { channel[chan].oct++; channel[chan].freq >>= 1; - } - else + } else channel[chan].freq = 686; } } -void -CmodPlayer::tone_portamento (unsigned char chan, unsigned char info) +void CmodPlayer::tone_portamento(unsigned char chan, unsigned char info) { - if (channel[chan].freq + (channel[chan].oct << 10) < - channel[chan].nextfreq + (channel[chan].nextoct << 10)) - { - slide_up (chan, info); - if (channel[chan].freq + (channel[chan].oct << 10) > - channel[chan].nextfreq + (channel[chan].nextoct << 10)) - { + if(channel[chan].freq + (channel[chan].oct << 10) < channel[chan].nextfreq + + (channel[chan].nextoct << 10)) { + slide_up(chan,info); + if(channel[chan].freq + (channel[chan].oct << 10) > channel[chan].nextfreq + + (channel[chan].nextoct << 10)) { channel[chan].freq = channel[chan].nextfreq; channel[chan].oct = channel[chan].nextoct; } } - if (channel[chan].freq + (channel[chan].oct << 10) > - channel[chan].nextfreq + (channel[chan].nextoct << 10)) - { - slide_down (chan, info); - if (channel[chan].freq + (channel[chan].oct << 10) < - channel[chan].nextfreq + (channel[chan].nextoct << 10)) - { + if(channel[chan].freq + (channel[chan].oct << 10) > channel[chan].nextfreq + + (channel[chan].nextoct << 10)) { + slide_down(chan,info); + if(channel[chan].freq + (channel[chan].oct << 10) < channel[chan].nextfreq + + (channel[chan].nextoct << 10)) { channel[chan].freq = channel[chan].nextfreq; channel[chan].oct = channel[chan].nextoct; } } - setfreq (chan); + setfreq(chan); } -void -CmodPlayer::vibrato (unsigned char chan, unsigned char speed, - unsigned char depth) +void CmodPlayer::vibrato(unsigned char chan, unsigned char speed, unsigned char depth) { int i; - if (!speed || !depth) + if(!speed || !depth) return; - if (depth > 14) + if(depth > 14) depth = 14; - for (i = 0; i < speed; i++) - { + for(i=0;i<speed;i++) { channel[chan].trigger++; - while (channel[chan].trigger >= 64) + while(channel[chan].trigger >= 64) channel[chan].trigger -= 64; - if (channel[chan].trigger >= 16 && channel[chan].trigger < 48) - slide_down (chan, - vibratotab[channel[chan].trigger - 16] / (16 - depth)); - if (channel[chan].trigger < 16) - slide_up (chan, vibratotab[channel[chan].trigger + 16] / (16 - depth)); - if (channel[chan].trigger >= 48) - slide_up (chan, vibratotab[channel[chan].trigger - 48] / (16 - depth)); + if(channel[chan].trigger >= 16 && channel[chan].trigger < 48) + slide_down(chan,vibratotab[channel[chan].trigger - 16] / (16-depth)); + if(channel[chan].trigger < 16) + slide_up(chan,vibratotab[channel[chan].trigger + 16] / (16-depth)); + if(channel[chan].trigger >= 48) + slide_up(chan,vibratotab[channel[chan].trigger - 48] / (16-depth)); } - setfreq (chan); + setfreq(chan); } -void -CmodPlayer::vol_up (unsigned char chan, int amount) +void CmodPlayer::vol_up(unsigned char chan, int amount) { - if (channel[chan].vol1 + amount < 63) + if(channel[chan].vol1 + amount < 63) channel[chan].vol1 += amount; else channel[chan].vol1 = 63; - if (channel[chan].vol2 + amount < 63) + if(channel[chan].vol2 + amount < 63) channel[chan].vol2 += amount; else channel[chan].vol2 = 63; } -void -CmodPlayer::vol_down (unsigned char chan, int amount) +void CmodPlayer::vol_down(unsigned char chan, int amount) { - if (channel[chan].vol1 - amount > 0) + if(channel[chan].vol1 - amount > 0) channel[chan].vol1 -= amount; else channel[chan].vol1 = 0; - if (channel[chan].vol2 - amount > 0) + if(channel[chan].vol2 - amount > 0) channel[chan].vol2 -= amount; else channel[chan].vol2 = 0; } -void -CmodPlayer::vol_up_alt (unsigned char chan, int amount) +void CmodPlayer::vol_up_alt(unsigned char chan, int amount) { - if (channel[chan].vol1 + amount < 63) + if(channel[chan].vol1 + amount < 63) channel[chan].vol1 += amount; else channel[chan].vol1 = 63; - if (inst[channel[chan].inst].data[0] & 1) - { - if (channel[chan].vol2 + amount < 63) + if(inst[channel[chan].inst].data[0] & 1) { + if(channel[chan].vol2 + amount < 63) channel[chan].vol2 += amount; else channel[chan].vol2 = 63; } } -void -CmodPlayer::vol_down_alt (unsigned char chan, int amount) +void CmodPlayer::vol_down_alt(unsigned char chan, int amount) { - if (channel[chan].vol1 - amount > 0) + if(channel[chan].vol1 - amount > 0) channel[chan].vol1 -= amount; else channel[chan].vol1 = 0; - if (inst[channel[chan].inst].data[0] & 1) - { - if (channel[chan].vol2 - amount > 0) + if(inst[channel[chan].inst].data[0] & 1) { + if(channel[chan].vol2 - amount > 0) channel[chan].vol2 -= amount; else channel[chan].vol2 = 0; diff --git a/src/adplug/core/psi.cc b/src/adplug/core/psi.cc index 3835ecf..720cc8a 100644 --- a/src/adplug/core/psi.cc +++ b/src/adplug/core/psi.cc @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -38,8 +38,8 @@ #include "psi.h" #include "debug.h" -const unsigned char - CxadpsiPlayer::psi_adlib_registers[99] = { +const unsigned char CxadpsiPlayer::psi_adlib_registers[99] = +{ 0x20, 0x23, 0x40, 0x43, 0x60, 0x63, 0x80, 0x83, 0xE0, 0xE3, 0xC0, 0x21, 0x24, 0x41, 0x44, 0x61, 0x64, 0x81, 0x84, 0xE1, 0xE4, 0xC1, 0x22, 0x25, 0x42, 0x45, 0x62, 0x65, 0x82, 0x85, 0xE2, 0xE5, 0xC2, @@ -51,25 +51,23 @@ const unsigned char 0x32, 0x35, 0x52, 0x55, 0x72, 0x75, 0x92, 0x95, 0xF2, 0xF5, 0xC8 }; -const unsigned short - CxadpsiPlayer::psi_notes[16] = { +const unsigned short CxadpsiPlayer::psi_notes[16] = +{ 0x216B, 0x2181, 0x2198, 0x21B0, 0x21CA, 0x21E5, 0x2202, 0x2220, 0x2241, 0x2263, 0x2287, 0x2364, - 0x0000, 0x0000, 0x0000, 0x0000 // by riven + 0x0000, 0x0000, 0x0000, 0x0000 // by riven }; -CPlayer * -CxadpsiPlayer::factory (Copl * newopl) +CPlayer *CxadpsiPlayer::factory(Copl *newopl) { - return new CxadpsiPlayer (newopl); + return new CxadpsiPlayer(newopl); } -void -CxadpsiPlayer::xadplayer_rewind (int subsong) +void CxadpsiPlayer::xadplayer_rewind(int subsong) { - opl_write (0x01, 0x20); - opl_write (0x08, 0x00); - opl_write (0xBD, 0x00); + opl_write(0x01, 0x20); + opl_write(0x08, 0x00); + opl_write(0xBD, 0x00); // get header header.instr_ptr = (tune[1] << 8) + tune[0]; @@ -78,18 +76,16 @@ CxadpsiPlayer::xadplayer_rewind (int subsong) // define instruments psi.instr_table = &tune[header.instr_ptr]; - for (int i = 0; i < 8; i++) + for(int i=0; i<8; i++) { - for (int j = 0; j < 11; j++) - { - unsigned short inspos = - (psi.instr_table[i * 2 + 1] << 8) + psi.instr_table[i * 2]; + for(int j=0; j<11; j++) { + unsigned short inspos = (psi.instr_table[i * 2 + 1] << 8) + psi.instr_table[i * 2]; - opl_write (psi_adlib_registers[i * 11 + j], tune[inspos + j]); + opl_write(psi_adlib_registers[i*11 + j],tune[inspos + j]); } - opl_write (0xA0 + i, 0x00); - opl_write (0xB0 + i, 0x00); + opl_write(0xA0+i, 0x00); + opl_write(0xB0+i, 0x00); psi.note_delay[i] = 1; psi.note_curdelay[i] = 1; @@ -100,38 +96,34 @@ CxadpsiPlayer::xadplayer_rewind (int subsong) psi.seq_table = &tune[header.seq_ptr]; } -void -CxadpsiPlayer::xadplayer_update () +void CxadpsiPlayer::xadplayer_update() { unsigned short ptr; - for (int i = 0; i < 8; i++) + for(int i=0; i<8; i++) { - ptr = - (psi.seq_table[(i << 1) * 2 + 1] << 8) + psi.seq_table[(i << 1) * 2]; + ptr = (psi.seq_table[(i<<1) * 2 + 1] << 8) + psi.seq_table[(i<<1) * 2]; psi.note_curdelay[i]--; if (!psi.note_curdelay[i]) { - opl_write (0xA0 + i, 0x00); - opl_write (0xB0 + i, 0x00); + opl_write(0xA0+i, 0x00); + opl_write(0xB0+i, 0x00); unsigned char event = tune[ptr++]; #ifdef DEBUG - AdPlug_LogWrite ("channel %02X, event %02X:\n", i + 1, event); + AdPlug_LogWrite("channel %02X, event %02X:\n",i+1,event); #endif // end of sequence ? if (!event) { - ptr = - (psi.seq_table[(i << 1) * 2 + 3] << 8) + - psi.seq_table[(i << 1) * 2 + 2]; + ptr = (psi.seq_table[(i<<1) * 2 + 3] << 8) + psi.seq_table[(i<<1) * 2 + 2]; event = tune[ptr++]; #ifdef DEBUG - AdPlug_LogWrite (" channel %02X, event %02X:\n", i + 1, event); + AdPlug_LogWrite(" channel %02X, event %02X:\n",i+1,event); #endif // set sequence loop flag @@ -139,7 +131,7 @@ CxadpsiPlayer::xadplayer_update () // module loop ? plr.looping = 1; - for (int j = 0; j < 8; j++) + for(int j=0; j<8; j++) plr.looping &= psi.looping[j]; } @@ -150,7 +142,7 @@ CxadpsiPlayer::xadplayer_update () event = tune[ptr++]; #ifdef DEBUG - AdPlug_LogWrite (" channel %02X, event %02X:\n", i + 1, event); + AdPlug_LogWrite(" channel %02X, event %02X:\n",i+1,event); #endif } @@ -159,29 +151,27 @@ CxadpsiPlayer::xadplayer_update () // play note unsigned short note = psi_notes[event & 0x0F]; - opl_write (0xA0 + i, note & 0xFF); - opl_write (0xB0 + i, (note >> 8) + ((event >> 2) & 0xFC)); + opl_write(0xA0+i, note & 0xFF); + opl_write(0xB0+i, (note >> 8) + ((event >> 2) & 0xFC)); // save position - psi.seq_table[(i << 1) * 2] = ptr & 0xff; - psi.seq_table[(i << 1) * 2 + 1] = ptr >> 8; + psi.seq_table[(i<<1) * 2] = ptr & 0xff; + psi.seq_table[(i<<1) * 2 + 1] = ptr >> 8; } } } -float -CxadpsiPlayer::xadplayer_getrefresh () +float CxadpsiPlayer::xadplayer_getrefresh() { return 70.0f; } -std::string CxadpsiPlayer::xadplayer_gettype () +std::string CxadpsiPlayer::xadplayer_gettype() { - return std::string ("xad: psi player"); + return std::string("xad: psi player"); } -unsigned int -CxadpsiPlayer::xadplayer_getinstruments () +unsigned int CxadpsiPlayer::xadplayer_getinstruments() { return 8; } diff --git a/src/adplug/core/psi.h b/src/adplug/core/psi.h index df149ac..8fbff06 100644 --- a/src/adplug/core/psi.h +++ b/src/adplug/core/psi.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -45,12 +45,12 @@ protected: unsigned char looping[9]; } psi; // - bool xadplayer_load() + bool xadplayer_load() { if(xad.fmt == PSI) - return true; + return true; else - return false; + return false; } void xadplayer_rewind(int subsong); void xadplayer_update(); diff --git a/src/adplug/core/rad.cc b/src/adplug/core/rad.cc index d9ae560..49cacea 100644 --- a/src/adplug/core/rad.cc +++ b/src/adplug/core/rad.cc @@ -22,133 +22,103 @@ * some volumes are dropped out */ -#include <string.h> - +#include <cstring> #include "rad.h" -CPlayer * -CradLoader::factory (Copl * newopl) +CPlayer *CradLoader::factory(Copl *newopl) { - return new CradLoader (newopl); + return new CradLoader(newopl); } -bool -CradLoader::load (VFSFile & fd, const CFileProvider & fp) +bool CradLoader::load(const std::string &filename, const CFileProvider &fp) { - binistream *f = fp.open (fd); - if (!f) - return false; + binistream *f = fp.open(filename); if(!f) return false; char id[16]; - unsigned char buf, ch, c, b, inp; + unsigned char buf,ch,c,b,inp; char bufstr[2] = "\0"; - unsigned int i, j; + unsigned int i,j; unsigned short patofs[32]; - const unsigned char convfx[16] = - { 255, 1, 2, 3, 255, 5, 255, 255, 255, 255, 20, 255, 17, 0xd, 255, 19 }; + const unsigned char convfx[16] = {255,1,2,3,255,5,255,255,255,255,20,255,17,0xd,255,19}; // file validation section - f->readString (id, 16); - version = f->readInt (1); - if (strncmp (id, "RAD by REALiTY!!", 16) || version != 0x10) - { - fp.close (f); - return false; - } + f->readString(id, 16); version = f->readInt(1); + if(strncmp(id,"RAD by REALiTY!!",16) || version != 0x10) + { fp.close(f); return false; } // load section - radflags = f->readInt (1); - if (radflags & 128) - { // description - memset (desc, 0, 80 * 22); - while ((buf = f->readInt (1))) - if (buf == 1) - strcat (desc, "\n"); - else if (buf >= 2 && buf <= 0x1f) - for (i = 0; i < buf; i++) - strcat (desc, " "); + radflags = f->readInt(1); + if(radflags & 128) { // description + memset(desc,0,80*22); + while((buf = f->readInt(1))) + if(buf == 1) + strcat(desc,"\n"); else - { - *bufstr = buf; - strcat (desc, bufstr); - } + if(buf >= 2 && buf <= 0x1f) + for(i=0;i<buf;i++) + strcat(desc," "); + else { + *bufstr = buf; + strcat(desc,bufstr); + } } - while ((buf = f->readInt (1))) - { // instruments + while((buf = f->readInt(1))) { // instruments buf--; - inst[buf].data[2] = f->readInt (1); - inst[buf].data[1] = f->readInt (1); - inst[buf].data[10] = f->readInt (1); - inst[buf].data[9] = f->readInt (1); - inst[buf].data[4] = f->readInt (1); - inst[buf].data[3] = f->readInt (1); - inst[buf].data[6] = f->readInt (1); - inst[buf].data[5] = f->readInt (1); - inst[buf].data[0] = f->readInt (1); - inst[buf].data[8] = f->readInt (1); - inst[buf].data[7] = f->readInt (1); + inst[buf].data[2] = f->readInt(1); inst[buf].data[1] = f->readInt(1); + inst[buf].data[10] = f->readInt(1); inst[buf].data[9] = f->readInt(1); + inst[buf].data[4] = f->readInt(1); inst[buf].data[3] = f->readInt(1); + inst[buf].data[6] = f->readInt(1); inst[buf].data[5] = f->readInt(1); + inst[buf].data[0] = f->readInt(1); + inst[buf].data[8] = f->readInt(1); inst[buf].data[7] = f->readInt(1); } - length = f->readInt (1); - for (i = 0; i < length; i++) - order[i] = f->readInt (1); // orderlist - for (i = 0; i < 32; i++) - patofs[i] = f->readInt (2); // pattern offset table - init_trackord (); // patterns - for (i = 0; i < 32; i++) - if (patofs[i]) - { - f->seek (patofs[i]); - do - { - buf = f->readInt (1); - b = buf & 127; - do - { - ch = f->readInt (1); - c = ch & 127; - inp = f->readInt (1); - tracks[i * 9 + c][b].note = inp & 127; - tracks[i * 9 + c][b].inst = (inp & 128) >> 3; - inp = f->readInt (1); - tracks[i * 9 + c][b].inst += inp >> 4; - tracks[i * 9 + c][b].command = inp & 15; - if (inp & 15) - { - inp = f->readInt (1); - tracks[i * 9 + c][b].param1 = inp / 10; - tracks[i * 9 + c][b].param2 = inp % 10; + length = f->readInt(1); + for(i = 0; i < length; i++) order[i] = f->readInt(1); // orderlist + for(i = 0; i < 32; i++) patofs[i] = f->readInt(2); // pattern offset table + init_trackord(); // patterns + for(i=0;i<32;i++) + if(patofs[i]) { + f->seek(patofs[i]); + do { + buf = f->readInt(1); b = buf & 127; + do { + ch = f->readInt(1); c = ch & 127; + inp = f->readInt(1); + tracks[i*9+c][b].note = inp & 127; + tracks[i*9+c][b].inst = (inp & 128) >> 3; + inp = f->readInt(1); + tracks[i*9+c][b].inst += inp >> 4; + tracks[i*9+c][b].command = inp & 15; + if(inp & 15) { + inp = f->readInt(1); + tracks[i*9+c][b].param1 = inp / 10; + tracks[i*9+c][b].param2 = inp % 10; } - } while (!(ch & 128)); - } while (!(buf & 128)); - } - else - memset (trackord[i], 0, 9 * 2); - fp.close (f); + } while(!(ch & 128)); + } while(!(buf & 128)); + } else + memset(trackord[i],0,9*2); + fp.close(f); // convert replay data - for (i = 0; i < 32 * 9; i++) // convert patterns - for (j = 0; j < 64; j++) - { - if (tracks[i][j].note == 15) + for(i=0;i<32*9;i++) // convert patterns + for(j=0;j<64;j++) { + if(tracks[i][j].note == 15) tracks[i][j].note = 127; - if (tracks[i][j].note > 16 && tracks[i][j].note < 127) + if(tracks[i][j].note > 16 && tracks[i][j].note < 127) tracks[i][j].note -= 4 * (tracks[i][j].note >> 4); - if (tracks[i][j].note && tracks[i][j].note < 126) + if(tracks[i][j].note && tracks[i][j].note < 126) tracks[i][j].note++; tracks[i][j].command = convfx[tracks[i][j].command]; } - restartpos = 0; - initspeed = radflags & 31; - bpm = radflags & 64 ? 0 : 50; - flags = Decimal; + restartpos = 0; initspeed = radflags & 31; + bpm = radflags & 64 ? 0 : 50; flags = Decimal; - rewind (0); + rewind(0); return true; } -float -CradLoader::getrefresh () +float CradLoader::getrefresh() { - if (tempo) + if(tempo) return (float) (tempo); else return 18.2f; diff --git a/src/adplug/core/rad.h b/src/adplug/core/rad.h index 693bb33..ac4ce73 100644 --- a/src/adplug/core/rad.h +++ b/src/adplug/core/rad.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -26,19 +26,19 @@ class CradLoader: public CmodPlayer public: static CPlayer *factory(Copl *newopl); - CradLoader(Copl *newopl) - : CmodPlayer(newopl) - { *desc = '\0'; }; + CradLoader(Copl *newopl) + : CmodPlayer(newopl) + { *desc = '\0'; }; - bool load(VFSFile &fd, const CFileProvider &fp); - float getrefresh(); + bool load(const std::string &filename, const CFileProvider &fp); + float getrefresh(); - std::string gettype() - { return std::string("Reality ADlib Tracker"); }; - std::string getdesc() - { return std::string(desc); }; + std::string gettype() + { return std::string("Reality ADlib Tracker"); }; + std::string getdesc() + { return std::string(desc); }; private: - unsigned char version,radflags; - char desc[80*22]; + unsigned char version,radflags; + char desc[80*22]; }; diff --git a/src/adplug/core/rat.cc b/src/adplug/core/rat.cc index ee26b20..3b3a6bf 100644 --- a/src/adplug/core/rat.cc +++ b/src/adplug/core/rat.cc @@ -29,41 +29,37 @@ comment : there are bug in original replayer's adlib_init(): wrong frequency registers. */ -#include <string.h> - +#include <cstring> #include "rat.h" #include "debug.h" -const unsigned char - CxadratPlayer::rat_adlib_bases[18] = { +const unsigned char CxadratPlayer::rat_adlib_bases[18] = +{ 0x00, 0x01, 0x02, 0x08, 0x09, 0x0A, 0x10, 0x11, 0x12, 0x03, 0x04, 0x05, 0x0B, 0x0C, 0x0D, 0x13, 0x14, 0x15 }; -const unsigned short - CxadratPlayer::rat_notes[16] = { - 0x157, 0x16B, 0x181, 0x198, 0x1B0, 0x1CA, 0x1E5, 0x202, 0x220, 0x241, 0x263, - 0x287, - 0x000, 0x000, 0x000, 0x000 // by riven +const unsigned short CxadratPlayer::rat_notes[16] = +{ + 0x157, 0x16B, 0x181, 0x198, 0x1B0, 0x1CA, 0x1E5, 0x202, 0x220, 0x241, 0x263, 0x287, + 0x000, 0x000, 0x000, 0x000 // by riven }; -CPlayer * -CxadratPlayer::factory (Copl * newopl) +CPlayer *CxadratPlayer::factory(Copl *newopl) { - return new CxadratPlayer (newopl); + return new CxadratPlayer(newopl); } -bool -CxadratPlayer::xadplayer_load () +bool CxadratPlayer::xadplayer_load() { - if (xad.fmt != RAT) + if(xad.fmt != RAT) return false; // load header - memcpy (&rat.hdr, &tune[0], sizeof (rat_header)); + memcpy(&rat.hdr, &tune[0], sizeof(rat_header)); // is 'RAT'-signed ? - if (strncmp (rat.hdr.id, "RAT", 3)) + if (strncmp(rat.hdr.id,"RAT",3)) return false; // is version 1.0 ? @@ -74,26 +70,25 @@ CxadratPlayer::xadplayer_load () rat.order = &tune[0x40]; // load instruments - rat.inst = (rat_instrument *) & tune[0x140]; + rat.inst = (rat_instrument *)&tune[0x140]; // load pattern data unsigned short patseg = (rat.hdr.patseg[1] << 8) + rat.hdr.patseg[0]; unsigned char *event_ptr = &tune[patseg << 4]; - for (int i = 0; i < rat.hdr.numpat; i++) - for (int j = 0; j < 64; j++) - for (int k = 0; k < rat.hdr.numchan; k++) + for(int i=0;i<rat.hdr.numpat;i++) + for(int j=0;j<64;j++) + for(int k=0;k<rat.hdr.numchan;k++) { - memcpy (&rat.tracks[i][j][k], event_ptr, sizeof (rat_event)); + memcpy(&rat.tracks[i][j][k], event_ptr, sizeof(rat_event)); - event_ptr += sizeof (rat_event); + event_ptr += sizeof(rat_event); } return true; } -void -CxadratPlayer::xadplayer_rewind (int subsong) +void CxadratPlayer::xadplayer_rewind(int subsong) { int i; @@ -104,44 +99,41 @@ CxadratPlayer::xadplayer_rewind (int subsong) plr.speed = rat.hdr.speed; // clear channel data - memset (&rat.channel, 0, sizeof (rat.channel[0]) * 9); + memset(&rat.channel, 0, sizeof(rat.channel[0])*9); // init OPL - opl_write (0x01, 0x20); - opl_write (0x08, 0x00); - opl_write (0xBD, 0x00); + opl_write(0x01, 0x20); + opl_write(0x08, 0x00); + opl_write(0xBD, 0x00); // set default frequencies - for (i = 0; i < 9; i++) + for(i=0;i<9;i++) { - opl_write (0xA0 + i, 0x00); - opl_write (0xA3 + i, 0x00); - opl_write (0xB0 + i, 0x00); - opl_write (0xB3 + i, 0x00); + opl_write(0xA0+i, 0x00); + opl_write(0xA3+i, 0x00); + opl_write(0xB0+i, 0x00); + opl_write(0xB3+i, 0x00); } // set default volumes - for (i = 0; i < 0x1F; i++) - opl_write (0x40 + i, 0x3F); + for(i=0;i<0x1F;i++) + opl_write(0x40+i, 0x3F); } -void -CxadratPlayer::xadplayer_update () +void CxadratPlayer::xadplayer_update() { int i; rat_event event; // process events - for (i = 0; i < rat.hdr.numchan; i++) + for(i=0;i<rat.hdr.numchan;i++) { - memcpy (&event, &rat.tracks[rat.order[rat.order_pos]][rat.pattern_pos][i], - sizeof (rat_event)); + memcpy(&event,&rat.tracks[rat.order[rat.order_pos]][rat.pattern_pos][i],sizeof(rat_event)); #ifdef DEBUG - AdPlug_LogWrite - ("order %02X, pattern %02X, row %02X, channel %02X, event %02X %02X %02X %02X %02X:\n", - rat.order_pos, rat.order[rat.order_pos], rat.pattern_pos, i, - event.note, event.instrument, event.volume, event.fx, event.fxp); + AdPlug_LogWrite("order %02X, pattern %02X, row %02X, channel %02X, event %02X %02X %02X %02X %02X:\n", + rat.order_pos, rat.order[rat.order_pos], rat.pattern_pos, i, event.note, event.instrument, event.volume, event.fx, event.fxp + ); #endif // is instrument ? @@ -159,8 +151,8 @@ CxadratPlayer::xadplayer_update () if (event.note != 0xFF) { // mute channel - opl_write (0xB0 + i, 0x00); - opl_write (0xA0 + i, 0x00); + opl_write(0xB0+i, 0x00); + opl_write(0xA0+i, 0x00); // if note != 0xFE then play if (event.note != 0xFE) @@ -168,39 +160,34 @@ CxadratPlayer::xadplayer_update () unsigned char ins = rat.channel[i].instrument; // synthesis/feedback - opl_write (0xC0 + i, rat.inst[ins].connect); + opl_write(0xC0+i, rat.inst[ins].connect); // controls - opl_write (0x20 + rat_adlib_bases[i], rat.inst[ins].mod_ctrl); - opl_write (0x20 + rat_adlib_bases[i + 9], rat.inst[ins].car_ctrl); + opl_write(0x20+rat_adlib_bases[i], rat.inst[ins].mod_ctrl); + opl_write(0x20+rat_adlib_bases[i+9], rat.inst[ins].car_ctrl); // volumes - opl_write (0x40 + rat_adlib_bases[i], - __rat_calc_volume (rat.inst[ins].mod_volume, - rat.channel[i].volume, rat.volume)); - opl_write (0x40 + rat_adlib_bases[i + 9], - __rat_calc_volume (rat.inst[ins].car_volume, - rat.channel[i].volume, rat.volume)); + opl_write(0x40+rat_adlib_bases[i], __rat_calc_volume(rat.inst[ins].mod_volume,rat.channel[i].volume,rat.volume)); + opl_write(0x40+rat_adlib_bases[i+9], __rat_calc_volume(rat.inst[ins].car_volume,rat.channel[i].volume,rat.volume)); // attack/decay - opl_write (0x60 + rat_adlib_bases[i], rat.inst[ins].mod_AD); - opl_write (0x60 + rat_adlib_bases[i + 9], rat.inst[ins].car_AD); + opl_write(0x60+rat_adlib_bases[i], rat.inst[ins].mod_AD); + opl_write(0x60+rat_adlib_bases[i+9], rat.inst[ins].car_AD); // sustain/release - opl_write (0x80 + rat_adlib_bases[i], rat.inst[ins].mod_SR); - opl_write (0x80 + rat_adlib_bases[i + 9], rat.inst[ins].car_SR); + opl_write(0x80+rat_adlib_bases[i], rat.inst[ins].mod_SR); + opl_write(0x80+rat_adlib_bases[i+9], rat.inst[ins].car_SR); // waveforms - opl_write (0xE0 + rat_adlib_bases[i], rat.inst[ins].mod_wave); - opl_write (0xE0 + rat_adlib_bases[i + 9], rat.inst[ins].car_wave); + opl_write(0xE0+rat_adlib_bases[i], rat.inst[ins].mod_wave); + opl_write(0xE0+rat_adlib_bases[i+9], rat.inst[ins].car_wave); // octave/frequency - unsigned short insfreq = - (rat.inst[ins].freq[1] << 8) + rat.inst[ins].freq[0]; + unsigned short insfreq = (rat.inst[ins].freq[1] << 8) + rat.inst[ins].freq[0]; unsigned short freq = insfreq * rat_notes[event.note & 0x0F] / 0x20AB; - opl_write (0xA0 + i, freq & 0xFF); - opl_write (0xB0 + i, (freq >> 8) | ((event.note & 0xF0) >> 2) | 0x20); + opl_write(0xA0+i, freq & 0xFF); + opl_write(0xB0+i, (freq >> 8) | ((event.note & 0xF0) >> 2) | 0x20); } } @@ -216,30 +203,30 @@ CxadratPlayer::xadplayer_update () rat.pattern_pos++; // process effects - for (i = 0; i < rat.hdr.numchan; i++) + for(i=0;i<rat.hdr.numchan;i++) { unsigned char old_order_pos = rat.order_pos; switch (rat.channel[i].fx) { - case 0x01: // 0x01: Set Speed - plr.speed = rat.channel[i].fxp; - break; - case 0x02: // 0x02: Position Jump - if (rat.channel[i].fxp < rat.hdr.order_end) - rat.order_pos = rat.channel[i].fxp; - else - rat.order_pos = 0; - - // jumpback ? - if (rat.order_pos <= old_order_pos) - plr.looping = 1; - - rat.pattern_pos = 0; - break; - case 0x03: // 0x03: Pattern Break (?) - rat.pattern_pos = 0x40; - break; + case 0x01: // 0x01: Set Speed + plr.speed = rat.channel[i].fxp; + break; + case 0x02: // 0x02: Position Jump + if (rat.channel[i].fxp < rat.hdr.order_end) + rat.order_pos = rat.channel[i].fxp; + else + rat.order_pos = 0; + + // jumpback ? + if (rat.order_pos <= old_order_pos) + plr.looping = 1; + + rat.pattern_pos = 0; + break; + case 0x03: // 0x03: Pattern Break (?) + rat.pattern_pos = 0x40; + break; } rat.channel[i].fx = 0; @@ -262,50 +249,45 @@ CxadratPlayer::xadplayer_update () } } -float -CxadratPlayer::xadplayer_getrefresh () +float CxadratPlayer::xadplayer_getrefresh() { return 60.0f; } -std::string CxadratPlayer::xadplayer_gettype () +std::string CxadratPlayer::xadplayer_gettype() { - return (std::string ("xad: rat player")); + return (std::string("xad: rat player")); } -std::string CxadratPlayer::xadplayer_gettitle () +std::string CxadratPlayer::xadplayer_gettitle() { - return (std::string (rat.hdr.title, 32)); + return (std::string(rat.hdr.title,32)); } -unsigned int -CxadratPlayer::xadplayer_getinstruments () +unsigned int CxadratPlayer::xadplayer_getinstruments() { return rat.hdr.numinst; } /* -------- Internal Functions ---------------------------- */ -unsigned char -CxadratPlayer::__rat_calc_volume (unsigned char ivol, unsigned char cvol, - unsigned char gvol) +unsigned char CxadratPlayer::__rat_calc_volume(unsigned char ivol, unsigned char cvol, unsigned char gvol) { #ifdef DEBUG - AdPlug_LogWrite ("volumes: instrument %02X, channel %02X, global %02X:\n", - ivol, cvol, gvol); + AdPlug_LogWrite("volumes: instrument %02X, channel %02X, global %02X:\n", ivol, cvol, gvol); #endif unsigned short vol; - vol = ivol; - vol &= 0x3F; - vol ^= 0x3F; - vol *= cvol; - vol >>= 6; - vol *= gvol; - vol >>= 6; - vol ^= 0x3F; + vol = ivol; + vol &= 0x3F; + vol ^= 0x3F; + vol *= cvol; + vol >>= 6; + vol *= gvol; + vol >>= 6; + vol ^= 0x3F; - vol |= ivol & 0xC0; + vol |= ivol & 0xC0; return vol; } diff --git a/src/adplug/core/rat.h b/src/adplug/core/rat.h index 424a76b..79f4ad8 100644 --- a/src/adplug/core/rat.h +++ b/src/adplug/core/rat.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -68,12 +68,12 @@ protected: unsigned char reserved_2[2]; unsigned char mod_ctrl; unsigned char car_ctrl; - unsigned char mod_volume; - unsigned char car_volume; - unsigned char mod_AD; - unsigned char car_AD; - unsigned char mod_SR; - unsigned char car_SR; + unsigned char mod_volume; + unsigned char car_volume; + unsigned char mod_AD; + unsigned char car_AD; + unsigned char mod_SR; + unsigned char car_SR; unsigned char mod_wave; unsigned char car_wave; unsigned char connect; @@ -109,7 +109,7 @@ protected: void xadplayer_rewind(int subsong); void xadplayer_update(); float xadplayer_getrefresh(); - std::string xadplayer_gettype(); + std::string xadplayer_gettype(); std::string xadplayer_gettitle(); unsigned int xadplayer_getinstruments(); // diff --git a/src/adplug/core/raw.cc b/src/adplug/core/raw.cc index 4dfc8f3..0100a1f 100644 --- a/src/adplug/core/raw.cc +++ b/src/adplug/core/raw.cc @@ -19,111 +19,86 @@ * raw.c - RAW Player by Simon Peter <dn.tlp@gmx.net> */ -#include <string.h> - +#include <cstring> #include "raw.h" /*** public methods *************************************/ -CPlayer * -CrawPlayer::factory (Copl * newopl) +CPlayer *CrawPlayer::factory(Copl *newopl) { - return new CrawPlayer (newopl); + return new CrawPlayer(newopl); } -bool -CrawPlayer::load (VFSFile & fd, const CFileProvider & fp) +bool CrawPlayer::load(const std::string &filename, const CFileProvider &fp) { - binistream *f = fp.open (fd); - if (!f) - return false; + binistream *f = fp.open(filename); if(!f) return false; char id[8]; unsigned long i; // file validation section - f->readString (id, 8); - if (strncmp (id, "RAWADATA", 8)) - { - fp.close (f); - return false; - } + f->readString(id, 8); + if(strncmp(id,"RAWADATA",8)) { fp.close (f); return false; } // load section - clock = f->readInt (2); // clock speed - length = (fp.filesize (f) - 10) / 2; - data = new Tdata[length]; - for (i = 0; i < length; i++) - { - data[i].param = f->readInt (1); - data[i].command = f->readInt (1); + clock = f->readInt(2); // clock speed + length = (fp.filesize(f) - 10) / 2; + data = new Tdata [length]; + for(i = 0; i < length; i++) { + data[i].param = f->readInt(1); + data[i].command = f->readInt(1); } - fp.close (f); - rewind (0); + fp.close(f); + rewind(0); return true; } -bool -CrawPlayer::update () +bool CrawPlayer::update() { - bool setspeed; + bool setspeed; - if (pos >= length) - return false; + if(pos >= length) return false; - if (del) - { + if(del) { del--; return !songend; } - do - { + do { setspeed = false; - switch (data[pos].command) - { - case 0: - del = data[pos].param - 1; - break; + switch(data[pos].command) { + case 0: del = data[pos].param - 1; break; case 2: - if (!data[pos].param) - { + if(!data[pos].param) { pos++; speed = data[pos].param + (data[pos].command << 8); setspeed = true; - } - else - opl->setchip (data[pos].param - 1); + } else + opl->setchip(data[pos].param - 1); break; case 0xff: - if (data[pos].param == 0xff) - { - rewind (0); // auto-rewind song + if(data[pos].param == 0xff) { + rewind(0); // auto-rewind song songend = true; return !songend; } break; default: - opl->write (data[pos].command, data[pos].param); + opl->write(data[pos].command,data[pos].param); break; } - } while (data[pos++].command || setspeed); + } while(data[pos++].command || setspeed); return !songend; } -void -CrawPlayer::rewind (int subsong) +void CrawPlayer::rewind(int subsong) { - pos = del = 0; - speed = clock; - songend = false; - opl->init (); - opl->write (1, 32); // go to 9 channel mode + pos = del = 0; speed = clock; songend = false; + opl->init(); opl->write(1, 32); // go to 9 channel mode } -float -CrawPlayer::getrefresh () +float CrawPlayer::getrefresh() { return 1193180.0 / (speed ? speed : 0xffff); // timer oscillator speed / wait register = clock frequency } diff --git a/src/adplug/core/raw.h b/src/adplug/core/raw.h index 113b843..dd935b2 100644 --- a/src/adplug/core/raw.h +++ b/src/adplug/core/raw.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -26,27 +26,27 @@ class CrawPlayer: public CPlayer public: static CPlayer *factory(Copl *newopl); - CrawPlayer(Copl *newopl) - : CPlayer(newopl), data(0) - { }; - ~CrawPlayer() - { if(data) delete [] data; }; + CrawPlayer(Copl *newopl) + : CPlayer(newopl), data(0) + { }; + ~CrawPlayer() + { if(data) delete [] data; }; - bool load(VFSFile &fd, const CFileProvider &fp); - bool update(); - void rewind(int subsong); - float getrefresh(); + bool load(const std::string &filename, const CFileProvider &fp); + bool update(); + void rewind(int subsong); + float getrefresh(); - std::string gettype() - { return std::string("RdosPlay RAW"); }; + std::string gettype() + { return std::string("RdosPlay RAW"); }; protected: - struct Tdata { - unsigned char param, command; - } *data; + struct Tdata { + unsigned char param, command; + } *data; - unsigned long pos, length; - unsigned short clock, speed; - unsigned char del; - bool songend; + unsigned long pos, length; + unsigned short clock, speed; + unsigned char del; + bool songend; }; diff --git a/src/adplug/core/rix.cc b/src/adplug/core/rix.cc index 7ac365e..f12b99f 100644 --- a/src/adplug/core/rix.cc +++ b/src/adplug/core/rix.cc @@ -20,115 +20,84 @@ * BSPAL <BSPAL.ys168.com> */ -#include <cstdlib> -#include <string.h> - +#include <cstring> #include "rix.h" #include "debug.h" -#include <libaudcore/audstrings.h> - -const unsigned char -CrixPlayer::adflag[] = - { 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1 }; -const unsigned char -CrixPlayer::reg_data[] = - { 0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21 }; -const unsigned char -CrixPlayer::ad_C0_offs[] = - { 0, 1, 2, 0, 1, 2, 3, 4, 5, 3, 4, 5, 6, 7, 8, 6, 7, 8 }; -const unsigned char - CrixPlayer::modify[] = - { 0, 3, 1, 4, 2, 5, 6, 9, 7, 10, 8, 11, 12, 15, 13, 16, 14, 17, 12, - 15, 16, 0, 14, 0, 17, 0, 13, 0 -}; -const unsigned char - CrixPlayer::bd_reg_data[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x08, 0x04, 0x02, 0x01, - 0x00, 0x01, 0x01, 0x03, 0x0F, 0x05, 0x00, 0x01, 0x03, 0x0F, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x0F, 0x07, 0x00, 0x02, - 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, - 0x04, 0x00, 0x08, 0x0C, 0x0B, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, - 0x00, 0x00, 0x0D, 0x04, 0x00, 0x06, 0x0F, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x0C, 0x00, 0x0F, 0x0B, 0x00, 0x08, 0x05, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x0F, 0x0B, 0x00, - 0x07, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x0F, 0x0B, 0x00, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x0F, 0x0B, 0x00, 0x07, 0x05, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00 -}; -unsigned char - CrixPlayer::for40reg[] = - { 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, - 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F -}; -unsigned short - CrixPlayer::mus_time = 0x4268; +const unsigned char CrixPlayer::adflag[] = {0,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,1,1}; +const unsigned char CrixPlayer::reg_data[] = {0,1,2,3,4,5,8,9,10,11,12,13,16,17,18,19,20,21}; +const unsigned char CrixPlayer::ad_C0_offs[] = {0,1,2,0,1,2,3,4,5,3,4,5,6,7,8,6,7,8}; +const unsigned char CrixPlayer::modify[] = {0,3,1,4,2,5,6,9,7,10,8,11,12,15,13,16,14,17,12,\ + 15,16,0,14,0,17,0,13,0}; +const unsigned char CrixPlayer::bd_reg_data[] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0x10,0x08,0x04,0x02,0x01, + 0x00,0x01,0x01,0x03,0x0F,0x05,0x00,0x01,0x03,0x0F,0x00, + 0x00,0x00,0x01,0x00,0x00,0x01,0x01,0x0F,0x07,0x00,0x02, + 0x04,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x0A, + 0x04,0x00,0x08,0x0C,0x0B,0x00,0x00,0x00,0x01,0x00,0x00, + 0x00,0x00,0x0D,0x04,0x00,0x06,0x0F,0x00,0x00,0x00,0x00, + 0x01,0x00,0x00,0x0C,0x00,0x0F,0x0B,0x00,0x08,0x05,0x00, + 0x00,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x0F,0x0B,0x00, + 0x07,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00, + 0x0F,0x0B,0x00,0x05,0x05,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x01,0x00,0x0F,0x0B,0x00,0x07,0x05,0x00,0x00,0x00, + 0x00,0x00,0x00}; +unsigned char CrixPlayer::for40reg[] = {0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F, + 0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F,0x7F}; +unsigned short CrixPlayer::mus_time = 0x4268; /*** public methods *************************************/ -CPlayer * -CrixPlayer::factory (Copl * newopl) +CPlayer *CrixPlayer::factory(Copl *newopl) { - return new CrixPlayer (newopl); + return new CrixPlayer(newopl); } -CrixPlayer::CrixPlayer (Copl * newopl):CPlayer (newopl), flag_mkf (0), file_buffer (0), -buf_addr (0) +CrixPlayer::CrixPlayer(Copl *newopl) + : CPlayer(newopl), flag_mkf(0), file_buffer(0), buf_addr(0) { } -CrixPlayer::~CrixPlayer () +CrixPlayer::~CrixPlayer() { - if (file_buffer) - delete[]file_buffer; + if(file_buffer) + delete [] file_buffer; } -bool -CrixPlayer::load (VFSFile & fd, const CFileProvider & fp) -{ - binistream *f = fp.open (fd); - if (!f) - return false; - unsigned long i = 0; - std::string filename (fd.filename ()); +bool CrixPlayer::load(const std::string &filename, const CFileProvider &fp) +{ + binistream *f = fp.open(filename); if(!f) return false; + unsigned long i=0; - if (str_has_suffix_nocase (filename.c_str (), ".mkf")) + if(strcasecmp(filename.substr(filename.length()-4,4).c_str(),".mkf")==0) { - flag_mkf = 1; - f->seek (0); - int offset = f->readInt (4); - f->seek (offset); + flag_mkf=1; + f->seek(0); + int offset=f->readInt(4); + f->seek(offset); } - if (f->readInt (2) != 0x55aa) - { - fp.close (f); - return false; - } - file_buffer = new unsigned char[fp.filesize (f) + 1]; - f->seek (0); - while (!f->eof ()) - file_buffer[i++] = f->readInt (1); - length = i; - fp.close (f); - if (!flag_mkf) - buf_addr = file_buffer; - rewind (0); + if(f->readInt(2)!=0x55aa){ fp.close(f);return false; } + file_buffer = new unsigned char [fp.filesize(f) + 1]; + f->seek(0); + while(!f->eof()) + file_buffer[i++]=f->readInt(1); + length=i; + fp.close(f); + if(!flag_mkf) + buf_addr=file_buffer; + rewind(0); return true; } -bool -CrixPlayer::update () +bool CrixPlayer::update() { - int_08h_entry (); - return !play_end; + int_08h_entry(); + return !play_end; } -void -CrixPlayer::rewind (int subsong) +void CrixPlayer::rewind(int subsong) { - I = 0; - T = 0; + I = 0; T = 0; mus_block = 0; ins_block = 0; rhythm = 0; @@ -142,470 +111,385 @@ CrixPlayer::rewind (int subsong) play_end = 0; pos = index = 0; - memset (f_buffer, 0, sizeof (unsigned short) * 300); - memset (a0b0_data2, 0, sizeof (unsigned short) * 11); - memset (a0b0_data3, 0, 18); - memset (a0b0_data4, 0, 18); - memset (a0b0_data5, 0, 96); - memset (addrs_head, 0, 96); - memset (insbuf, 0, 28 * sizeof (unsigned short)); - memset (displace, 0, 11 * sizeof (unsigned short)); - memset (reg_bufs, 0, 18 * sizeof (ADDT)); - - if (flag_mkf) + memset(f_buffer, 0, sizeof(unsigned short) * 300); + memset(a0b0_data2, 0, sizeof(unsigned short) * 11); + memset(a0b0_data3, 0, 18); + memset(a0b0_data4, 0, 18); + memset(a0b0_data5, 0, 96); + memset(addrs_head, 0, 96); + memset(insbuf, 0, 28 * sizeof(unsigned short)); + memset(displace, 0, 11 * sizeof(unsigned short)); + memset(reg_bufs, 0, 18 * sizeof(ADDT)); + + if(flag_mkf) { - unsigned int *buf_index = (unsigned int *) file_buffer; - int offset1 = buf_index[subsong], offset2; - while ((offset2 = buf_index[++subsong]) == offset1); - length = offset2 - offset1 + 1; - buf_addr = file_buffer + offset1; + unsigned int *buf_index=(unsigned int *)file_buffer; + int offset1=buf_index[subsong],offset2; + while((offset2=buf_index[++subsong])==offset1); + length=offset2-offset1+1; + buf_addr=file_buffer+offset1; } - opl->init (); - opl->write (1, 32); // go to OPL2 mode - set_new_int (); - data_initial (); + opl->init(); + opl->write(1,32); // go to OPL2 mode + set_new_int(); + data_initial(); } -unsigned int -CrixPlayer::getsubsongs () +unsigned int CrixPlayer::getsubsongs() { - if (flag_mkf) - { - unsigned int *buf_index = (unsigned int *) file_buffer; - int songs = buf_index[0] / 4, i = 0; - for (i = 0; i < songs; i++) - if (buf_index[i + 1] == buf_index[i]) - songs--; - return songs; - } - else - return 1; + if(flag_mkf) + { + unsigned int *buf_index=(unsigned int *)file_buffer; + int songs=buf_index[0]/4,i=0; + for(i=0;i<songs;i++) + if(buf_index[i+1]==buf_index[i]) + songs--; + return songs; + } + else + return 1; } -float -CrixPlayer::getrefresh () +float CrixPlayer::getrefresh() { - return 70.0f; + return 70.0f; } /*------------------Implemention----------------------------*/ -inline void -CrixPlayer::set_new_int () +inline void CrixPlayer::set_new_int() { // if(!ad_initial()) exit(1); - ad_initial (); + ad_initial(); } - /*----------------------------------------------------------*/ -inline void -CrixPlayer::Pause () +inline void CrixPlayer::Pause() { unsigned short i; pause_flag = 1; - for (i = 0; i < 11; i++) - switch_ad_bd (i); + for(i=0;i<11;i++) + switch_ad_bd(i); } - /*----------------------------------------------------------*/ -inline void -CrixPlayer::ad_a0b0l_reg_ (unsigned short index, unsigned short p2, - unsigned short p3) +inline void CrixPlayer::ad_a0b0l_reg_(unsigned short index,unsigned short p2,unsigned short p3) { // unsigned short i = p2+a0b0_data2[index]; a0b0_data4[index] = p3; a0b0_data3[index] = p2; } -inline void -CrixPlayer::data_initial () +inline void CrixPlayer::data_initial() { rhythm = buf_addr[2]; - mus_block = (buf_addr[0x0D] << 8) + buf_addr[0x0C]; - ins_block = (buf_addr[0x09] << 8) + buf_addr[0x08]; - I = mus_block + 1; - if (rhythm != 0) - { - // ad_a0b0_reg(6); - // ad_a0b0_reg(7); - // ad_a0b0_reg(8); - ad_a0b0l_reg_ (8, 0x18, 0); - ad_a0b0l_reg_ (7, 0x1F, 0); - } + mus_block = (buf_addr[0x0D]<<8)+buf_addr[0x0C]; + ins_block = (buf_addr[0x09]<<8)+buf_addr[0x08]; + I = mus_block+1; + if(rhythm != 0) + { + // ad_a0b0_reg(6); + // ad_a0b0_reg(7); + // ad_a0b0_reg(8); + ad_a0b0l_reg_(8,0x18,0); + ad_a0b0l_reg_(7,0x1F,0); + } bd_modify = 0; // ad_bd_reg(); - band = 0; - music_on = 1; + band = 0; music_on = 1; } - /*----------------------------------------------------------*/ -inline unsigned short -CrixPlayer::ad_initial () +inline unsigned short CrixPlayer::ad_initial() { - unsigned short i, j, k = 0; - for (i = 0; i < 25; i++) + unsigned short i,j,k = 0; + for(i=0;i<25;i++) { - f_buffer[i * 12] = - (unsigned int) ((i * 24 + 10000) * 0.27461678223 + 4) >> 3; - for (int t = 1; t < 12; t++) - f_buffer[i * 12 + t] = - (unsigned int) ((double) f_buffer[i * 12 + t - 1] * 1.06); + f_buffer[i*12]=(unsigned int)((i*24+10000)*0.27461678223+4)>>3; + for(int t=1;t<12;t++) + f_buffer[i*12+t]=f_buffer[i*12+t-1]*1.06; } - for (i = 0; i < 8; i++) - for (j = 0; j < 12; j++) - { - a0b0_data5[k] = i; - addrs_head[k] = j; - k++; - } + for(i=0;i<8;i++) + for(j=0;j<12;j++) + { + a0b0_data5[k] = i; + addrs_head[k] = j; + k++; + } //ad_bd_reg(); //ad_08_reg(); //for(i=0;i<9;i++) ad_a0b0_reg(i); e0_reg_flag = 0x20; //for(i=0;i<18;i++) ad_bop(0xE0+reg_data[i],0); //ad_bop(1,e0_reg_flag); - return 1; //ad_test(); + return 1;//ad_test(); } - /*----------------------------------------------------------*/ -inline void -CrixPlayer::ad_bop (unsigned short reg, unsigned short value) +inline void CrixPlayer::ad_bop(unsigned short reg,unsigned short value) { - if (reg == 2 || reg == 3) - AdPlug_LogWrite ("switch OPL2/3 mode!\n"); - opl->write (reg & 0xff, value & 0xff); + if(reg == 2 || reg == 3) + AdPlug_LogWrite("switch OPL2/3 mode!\n"); + opl->write(reg & 0xff, value & 0xff); } - /*--------------------------------------------------------------*/ -inline void -CrixPlayer::int_08h_entry () -{ - unsigned short band_sus = 1; - while (band_sus) +inline void CrixPlayer::int_08h_entry() { - if (sustain <= 0) - { - band_sus = rix_proc (); - if (band_sus) - sustain += band_sus; - else + unsigned short band_sus = 1; + while(band_sus) { - play_end = 1; - break; + if(sustain <= 0) + { + band_sus = rix_proc(); + if(band_sus) sustain += band_sus; + else + { + play_end=1; + break; + } + } + else + { + if(band_sus) sustain -= 14; /* aging */ + break; + } } - } - else - { - if (band_sus) - sustain -= 14; /* aging */ - break; - } } -} - /*--------------------------------------------------------------*/ -inline unsigned short -CrixPlayer::rix_proc () +inline unsigned short CrixPlayer::rix_proc() { unsigned char ctrl = 0; - if (music_on == 0 || pause_flag == 1) - return 0; + if(music_on == 0||pause_flag == 1) return 0; band = 0; - while (buf_addr[I] != 0x80 && I < length - 1) - { - band_low = buf_addr[I - 1]; - ctrl = buf_addr[I]; - I += 2; - switch (ctrl & 0xF0) + while(buf_addr[I] != 0x80 && I<length-1) { - case 0x90: - rix_get_ins (); - rix_90_pro (ctrl & 0x0F); - break; - case 0xA0: - rix_A0_pro (ctrl & 0x0F, ((unsigned short) band_low) << 6); - break; - case 0xB0: - rix_B0_pro (ctrl & 0x0F, band_low); - break; - case 0xC0: - switch_ad_bd (ctrl & 0x0F); - if (band_low != 0) - rix_C0_pro (ctrl & 0x0F, band_low); - break; - default: - band = (ctrl << 8) + band_low; - break; + band_low = buf_addr[I-1]; + ctrl = buf_addr[I]; I+=2; + switch(ctrl&0xF0) + { + case 0x90: rix_get_ins(); rix_90_pro(ctrl&0x0F); break; + case 0xA0: rix_A0_pro(ctrl&0x0F,((unsigned short)band_low)<<6); break; + case 0xB0: rix_B0_pro(ctrl&0x0F,band_low); break; + case 0xC0: switch_ad_bd(ctrl&0x0F); + if(band_low != 0) rix_C0_pro(ctrl&0x0F,band_low); + break; + default: band = (ctrl<<8)+band_low; break; + } + if(band != 0) return band; } - if (band != 0) - return band; - } - music_ctrl (); - I = mus_block + 1; - band = 0; - music_on = 1; + music_ctrl(); + I = mus_block+1; + band = 0; music_on = 1; return 0; } - /*--------------------------------------------------------------*/ -inline void -CrixPlayer::rix_get_ins () +inline void CrixPlayer::rix_get_ins() { - int i; - unsigned char *baddr = (&buf_addr[ins_block]) + (band_low << 6); + int i; + unsigned char *baddr = (&buf_addr[ins_block])+(band_low<<6); - for (i = 0; i < 28; i++) + for(i = 0; i < 28; i++) insbuf[i] = (baddr[i * 2 + 1] << 8) + baddr[i * 2]; } - /*--------------------------------------------------------------*/ -inline void -CrixPlayer::rix_90_pro (unsigned short ctrl_l) +inline void CrixPlayer::rix_90_pro(unsigned short ctrl_l) { - if (rhythm == 0 || ctrl_l < 6) - { - ins_to_reg (modify[ctrl_l * 2], insbuf, insbuf[26]); - ins_to_reg (modify[ctrl_l * 2 + 1], insbuf + 13, insbuf[27]); - return; - } - else if (ctrl_l > 6) - { - ins_to_reg (modify[ctrl_l * 2 + 6], insbuf, insbuf[26]); - return; - } + if(rhythm == 0 || ctrl_l < 6) + { + ins_to_reg(modify[ctrl_l*2],insbuf,insbuf[26]); + ins_to_reg(modify[ctrl_l*2+1],insbuf+13,insbuf[27]); + return; + } + else if(ctrl_l > 6) + { + ins_to_reg(modify[ctrl_l*2+6],insbuf,insbuf[26]); + return; + } else - { - ins_to_reg (12, insbuf, insbuf[26]); - ins_to_reg (15, insbuf + 13, insbuf[27]); - return; - } + { + ins_to_reg(12,insbuf,insbuf[26]); + ins_to_reg(15,insbuf+13,insbuf[27]); + return; + } } - /*--------------------------------------------------------------*/ -inline void -CrixPlayer::rix_A0_pro (unsigned short ctrl_l, unsigned short index) +inline void CrixPlayer::rix_A0_pro(unsigned short ctrl_l,unsigned short index) { - if (rhythm == 0 || ctrl_l <= 6) - { - prepare_a0b0 (ctrl_l, index > 0x3FFF ? 0x3FFF : index); - ad_a0b0l_reg (ctrl_l, a0b0_data3[ctrl_l], a0b0_data4[ctrl_l]); - } - else - return; + if(rhythm == 0 || ctrl_l <= 6) + { + prepare_a0b0(ctrl_l,index>0x3FFF?0x3FFF:index); + ad_a0b0l_reg(ctrl_l,a0b0_data3[ctrl_l],a0b0_data4[ctrl_l]); + } + else return; } - /*--------------------------------------------------------------*/ -inline void -CrixPlayer::prepare_a0b0 (unsigned short index, unsigned short v) /* important ! */ -{ - short high = 0, low = 0; - unsigned int res; - int res1 = (v - 0x2000) * 0x19; - if (res1 == (int) 0xff) - return; - low = res1 / 0x2000; - if (low < 0) - { - low = 0x18 - low; - high = (signed short) low < 0 ? 0xFFFF : 0; - res = high; - res <<= 16; - res += low; - low = ((signed short) res) / (signed short) 0xFFE7; - a0b0_data2[index] = low; - low = res; - res = low - 0x18; - high = (signed short) res % 0x19; - low = (signed short) res / 0x19; - if (high != 0) +inline void CrixPlayer::prepare_a0b0(unsigned short index,unsigned short v) /* important !*/ +{ + short high = 0,low = 0; unsigned int res; + int res1 = (v-0x2000)*0x19; + if(res1 == (int)0xff) return; + low = res1/0x2000; + if(low < 0) { - low = 0x19; - low = low - high; + low = 0x18-low; high = (signed short)low<0?0xFFFF:0; + res = high; res<<=16; res+=low; + low = ((signed short)res)/(signed short)0xFFE7; + a0b0_data2[index] = low; + low = res; + res = low - 0x18; + high = (signed short)res%0x19; + low = (signed short)res/0x19; + if(high != 0) {low = 0x19; low = low-high;} } - } else - { - res = high = low; - low = (signed short) res / (signed short) 0x19; - a0b0_data2[index] = low; - res = high; - low = (signed short) res % (signed short) 0x19; - } - low = (signed short) low *(signed short) 0x18; + { + res = high = low; + low = (signed short)res/(signed short)0x19; + a0b0_data2[index] = low; + res = high; + low = (signed short)res%(signed short)0x19; + } + low = (signed short)low*(signed short)0x18; displace[index] = low; } - /*--------------------------------------------------------------*/ -inline void -CrixPlayer::ad_a0b0l_reg (unsigned short index, unsigned short p2, - unsigned short p3) +inline void CrixPlayer::ad_a0b0l_reg(unsigned short index,unsigned short p2,unsigned short p3) { - unsigned short data; - unsigned short i = p2 + a0b0_data2[index]; + unsigned short data; unsigned short i = p2+a0b0_data2[index]; a0b0_data4[index] = p3; a0b0_data3[index] = p2; - i = ((signed short) i <= 0x5F ? i : 0x5F); - i = ((signed short) i >= 0 ? i : 0); - data = f_buffer[addrs_head[i] + displace[index] / 2]; - ad_bop (0xA0 + index, data); - data = a0b0_data5[i] * 4 + (p3 < 1 ? 0 : 0x20) + ((data >> 8) & 3); - ad_bop (0xB0 + index, data); + i = ((signed short)i<=0x5F?i:0x5F); + i = ((signed short)i>=0?i:0); + data = f_buffer[addrs_head[i]+displace[index]/2]; + ad_bop(0xA0+index,data); + data = a0b0_data5[i]*4+(p3<1?0:0x20)+((data>>8)&3); + ad_bop(0xB0+index,data); } - /*--------------------------------------------------------------*/ -inline void -CrixPlayer::rix_B0_pro (unsigned short ctrl_l, unsigned short index) +inline void CrixPlayer::rix_B0_pro(unsigned short ctrl_l,unsigned short index) { int temp = 0; - if (rhythm == 0 || ctrl_l < 6) - temp = modify[ctrl_l * 2 + 1]; + if(rhythm == 0 || ctrl_l < 6) temp = modify[ctrl_l*2+1]; else - { - temp = ctrl_l > 6 ? ctrl_l * 2 : ctrl_l * 2 + 1; - temp = modify[temp + 6]; - } - for40reg[temp] = index > 0x7F ? 0x7F : index; - ad_40_reg (temp); + { + temp = ctrl_l > 6?ctrl_l*2:ctrl_l*2+1; + temp = modify[temp+6]; + } + for40reg[temp] = index>0x7F?0x7F:index; + ad_40_reg(temp); } - /*--------------------------------------------------------------*/ -inline void -CrixPlayer::rix_C0_pro (unsigned short ctrl_l, unsigned short index) +inline void CrixPlayer::rix_C0_pro(unsigned short ctrl_l,unsigned short index) { - unsigned short i = index >= 12 ? index - 12 : 0; - if (ctrl_l < 6 || rhythm == 0) - { - ad_a0b0l_reg (ctrl_l, i, 1); - return; - } + unsigned short i = index>=12?index-12:0; + if(ctrl_l < 6 || rhythm == 0) + { + ad_a0b0l_reg(ctrl_l,i,1); + return; + } else - { - if (ctrl_l != 6) { - if (ctrl_l == 8) - { - ad_a0b0l_reg (ctrl_l, i, 0); - ad_a0b0l_reg (7, i + 7, 0); - } + if(ctrl_l != 6) + { + if(ctrl_l == 8) + { + ad_a0b0l_reg(ctrl_l,i,0); + ad_a0b0l_reg(7,i+7,0); + } + } + else ad_a0b0l_reg(ctrl_l,i,0); + bd_modify |= bd_reg_data[ctrl_l]; + ad_bd_reg(); + return; } - else - ad_a0b0l_reg (ctrl_l, i, 0); - bd_modify |= bd_reg_data[ctrl_l]; - ad_bd_reg (); - return; - } } - /*--------------------------------------------------------------*/ -inline void -CrixPlayer::switch_ad_bd (unsigned short index) +inline void CrixPlayer::switch_ad_bd(unsigned short index) { - if (rhythm == 0 || index < 6) - ad_a0b0l_reg (index, a0b0_data3[index], 0); + if(rhythm == 0 || index < 6) ad_a0b0l_reg(index,a0b0_data3[index],0); else - { - bd_modify &= (~bd_reg_data[index]), ad_bd_reg (); - } + { + bd_modify &= (~bd_reg_data[index]), + ad_bd_reg(); + } } - /*--------------------------------------------------------------*/ -inline void -CrixPlayer::ins_to_reg (unsigned short index, unsigned short *insb, - unsigned short value) +inline void CrixPlayer::ins_to_reg(unsigned short index,unsigned short* insb,unsigned short value) { unsigned short i; - for (i = 0; i < 13; i++) - reg_bufs[index].v[i] = insb[i]; - reg_bufs[index].v[13] = value & 3; - ad_bd_reg (), ad_08_reg (), - ad_40_reg (index), ad_C0_reg (index), ad_60_reg (index), - ad_80_reg (index), ad_20_reg (index), ad_E0_reg (index); + for(i=0;i<13;i++) reg_bufs[index].v[i] = insb[i]; + reg_bufs[index].v[13] = value&3; + ad_bd_reg(),ad_08_reg(), + ad_40_reg(index),ad_C0_reg(index),ad_60_reg(index), + ad_80_reg(index),ad_20_reg(index),ad_E0_reg(index); } - /*--------------------------------------------------------------*/ -inline void -CrixPlayer::ad_E0_reg (unsigned short index) +inline void CrixPlayer::ad_E0_reg(unsigned short index) { - unsigned short data = e0_reg_flag == 0 ? 0 : (reg_bufs[index].v[13] & 3); - ad_bop (0xE0 + reg_data[index], data); + unsigned short data = e0_reg_flag == 0?0:(reg_bufs[index].v[13]&3); + ad_bop(0xE0+reg_data[index],data); } - /*--------------------------------------------------------------*/ -inline void -CrixPlayer::ad_20_reg (unsigned short index) +inline void CrixPlayer::ad_20_reg(unsigned short index) { - unsigned short data = (reg_bufs[index].v[9] < 1 ? 0 : 0x80); - data += (reg_bufs[index].v[10] < 1 ? 0 : 0x40); - data += (reg_bufs[index].v[5] < 1 ? 0 : 0x20); - data += (reg_bufs[index].v[11] < 1 ? 0 : 0x10); - data += (reg_bufs[index].v[1] & 0x0F); - ad_bop (0x20 + reg_data[index], data); + unsigned short data = (reg_bufs[index].v[9] < 1?0:0x80); + data += (reg_bufs[index].v[10] < 1?0:0x40); + data += (reg_bufs[index].v[5] < 1?0:0x20); + data += (reg_bufs[index].v[11] < 1?0:0x10); + data += (reg_bufs[index].v[1]&0x0F); + ad_bop(0x20+reg_data[index],data); } - /*--------------------------------------------------------------*/ -inline void -CrixPlayer::ad_80_reg (unsigned short index) +inline void CrixPlayer::ad_80_reg(unsigned short index) { - unsigned short data = (reg_bufs[index].v[7] & 0x0F), temp = - reg_bufs[index].v[4]; + unsigned short data = (reg_bufs[index].v[7]&0x0F),temp = reg_bufs[index].v[4]; data |= (temp << 4); - ad_bop (0x80 + reg_data[index], data); + ad_bop(0x80+reg_data[index],data); } - /*--------------------------------------------------------------*/ -inline void -CrixPlayer::ad_60_reg (unsigned short index) +inline void CrixPlayer::ad_60_reg(unsigned short index) { - unsigned short data = reg_bufs[index].v[6] & 0x0F, temp = - reg_bufs[index].v[3]; + unsigned short data = reg_bufs[index].v[6]&0x0F,temp = reg_bufs[index].v[3]; data |= (temp << 4); - ad_bop (0x60 + reg_data[index], data); + ad_bop(0x60+reg_data[index],data); } - /*--------------------------------------------------------------*/ -inline void -CrixPlayer::ad_C0_reg (unsigned short index) +inline void CrixPlayer::ad_C0_reg(unsigned short index) { unsigned short data = reg_bufs[index].v[2]; - if (adflag[index] == 1) - return; - data *= 2, data |= (reg_bufs[index].v[12] < 1 ? 1 : 0); - ad_bop (0xC0 + ad_C0_offs[index], data); + if(adflag[index] == 1) return; + data *= 2, + data |= (reg_bufs[index].v[12] < 1?1:0); + ad_bop(0xC0+ad_C0_offs[index],data); } - /*--------------------------------------------------------------*/ -inline void -CrixPlayer::ad_40_reg (unsigned short index) +inline void CrixPlayer::ad_40_reg(unsigned short index) { unsigned int res = 0; - unsigned short data = 0, temp = reg_bufs[index].v[0]; + unsigned short data = 0,temp = reg_bufs[index].v[0]; data = 0x3F - (0x3F & reg_bufs[index].v[8]), - data *= for40reg[index], data *= 2, data += 0x7F, res = data; - data = res / 0xFE, data -= 0x3F, data = -data, data |= temp << 6; - ad_bop (0x40 + reg_data[index], data); + data *= for40reg[index], + data *= 2, + data += 0x7F, + res = data; + data = res/0xFE, + data -= 0x3F, + data = -data, + data |= temp<<6; + ad_bop(0x40+reg_data[index],data); } - /*--------------------------------------------------------------*/ -inline void -CrixPlayer::ad_bd_reg () +inline void CrixPlayer::ad_bd_reg() { - unsigned short data = rhythm < 1 ? 0 : 0x20; + unsigned short data = rhythm < 1? 0:0x20; data |= bd_modify; - ad_bop (0xBD, data); + ad_bop(0xBD,data); } - /*--------------------------------------------------------------*/ -inline void -CrixPlayer::ad_a0b0_reg (unsigned short index) +inline void CrixPlayer::ad_a0b0_reg(unsigned short index) { - ad_bop (0xA0 + index, 0); - ad_bop (0xB0 + index, 0); + ad_bop(0xA0+index,0); + ad_bop(0xB0+index,0); } - /*--------------------------------------------------------------*/ -inline void -CrixPlayer::music_ctrl () +inline void CrixPlayer::music_ctrl() { int i; - for (i = 0; i < 11; i++) - switch_ad_bd (i); + for(i=0;i<11;i++) + switch_ad_bd(i); } diff --git a/src/adplug/core/rix.h b/src/adplug/core/rix.h index 5c83ac4..d3abe23 100644 --- a/src/adplug/core/rix.h +++ b/src/adplug/core/rix.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2006 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -30,7 +30,7 @@ class CrixPlayer: public CPlayer CrixPlayer(Copl *newopl); ~CrixPlayer(); - bool load(VFSFile &fd, const CFileProvider &fp); + bool load(const std::string &filename, const CFileProvider &fp); bool update(); void rewind(int subsong); float getrefresh(); @@ -39,7 +39,7 @@ class CrixPlayer: public CPlayer std::string gettype() { return std::string("Softstar RIX OPL Music Format"); }; - protected: + protected: typedef struct { unsigned char v[14]; } ADDT; diff --git a/src/adplug/core/rol.cc b/src/adplug/core/rol.cc index a910218..fc7e1e0 100644 --- a/src/adplug/core/rol.cc +++ b/src/adplug/core/rol.cc @@ -20,8 +20,8 @@ * * Visit: http://tenacity.hispeed.com/aomit/oplx/ */ +#include <cstring> #include <algorithm> -#include <string.h> #include "rol.h" #include "debug.h" @@ -66,7 +66,7 @@ CPlayer *CrolPlayer::factory(Copl *newopl) //--------------------------------------------------------- CrolPlayer::CrolPlayer(Copl *newopl) : CPlayer ( newopl ) - ,rol_header ( nullptr ) + ,rol_header ( NULL ) ,mNextTempoEvent ( 0 ) ,mCurrTick ( 0 ) ,mTimeOfLastNote ( 0 ) @@ -85,19 +85,18 @@ CrolPlayer::CrolPlayer(Copl *newopl) //--------------------------------------------------------- CrolPlayer::~CrolPlayer() { - if(rol_header) + if( rol_header != NULL ) { delete rol_header; - rol_header = 0; + rol_header=NULL; } } //--------------------------------------------------------- -bool CrolPlayer::load(VFSFile &fd, const CFileProvider &fp) +bool CrolPlayer::load(const std::string &filename, const CFileProvider &fp) { - binistream *f = fp.open(fd); if(!f) return false; - std::string filename(fd.filename ()); + binistream *f = fp.open(filename); if(!f) return false; - char *fn = new char[filename.length()+12]; + char *fn = new char[filename.length()+13]; int i; std::string bnk_filename; @@ -105,10 +104,10 @@ bool CrolPlayer::load(VFSFile &fd, const CFileProvider &fp) strcpy(fn,filename.data()); for (i=strlen(fn)-1; i>=0; i--) if (fn[i] == '/' || fn[i] == '\\') - break; + break; strcpy(fn+i+1,"standard.bnk"); bnk_filename = fn; - delete [] fn; fn = 0; + delete [] fn; AdPlug_LogWrite("bnk_filename = \"%s\"\n",bnk_filename.c_str()); rol_header = new SRolHeader; @@ -120,7 +119,7 @@ bool CrolPlayer::load(VFSFile &fd, const CFileProvider &fp) // Version check if(rol_header->version_major != 0 || rol_header->version_minor != 4) { AdPlug_LogWrite("Unsupported file version %d.%d or not a ROL file!\n", - rol_header->version_major, rol_header->version_minor); + rol_header->version_major, rol_header->version_minor); AdPlug_LogWrite("--- CrolPlayer::load ---\n"); fp.close(f); return false; @@ -258,9 +257,6 @@ void CrolPlayer::UpdateVoice( int const voice, CVoiceData &voiceData ) TVolumeEvents &vEvents = voiceData.volume_events; TPitchEvents &pEvents = voiceData.pitch_events; - if (iEvents.empty()) { - return; // prevent out-of-bounds access - } if( !(voiceData.mEventStatus & CVoiceData::kES_InstrEnd ) && iEvents[voiceData.next_instrument_event].time == mCurrTick ) { @@ -275,9 +271,6 @@ void CrolPlayer::UpdateVoice( int const voice, CVoiceData &voiceData ) } } - if (vEvents.empty()) { - return; // prevent out-of-bounds access - } if( !(voiceData.mEventStatus & CVoiceData::kES_VolumeEnd ) && vEvents[voiceData.next_volume_event].time == mCurrTick ) { @@ -321,9 +314,6 @@ void CrolPlayer::UpdateVoice( int const voice, CVoiceData &voiceData ) } } - if (pEvents.empty()) { - return; // prevent out-of-bounds access - } if( !(voiceData.mEventStatus & CVoiceData::kES_PitchEnd ) && pEvents[voiceData.next_pitch_event].time == mCurrTick ) { @@ -464,9 +454,6 @@ void CrolPlayer::load_tempo_events( binistream *f ) { int16 const num_tempo_events = f->readInt( 2 ); - if (num_tempo_events<0) { - return; - } mTempoEvents.reserve( num_tempo_events ); for(int i=0; i<num_tempo_events; ++i) @@ -482,8 +469,7 @@ void CrolPlayer::load_tempo_events( binistream *f ) bool CrolPlayer::load_voice_data( binistream *f, std::string const &bnk_filename, const CFileProvider &fp ) { SBnkHeader bnk_header; - VFSFile fd(bnk_filename.c_str(), "rb"); - binistream *bnk_file = fp.open(fd); + binistream *bnk_file = fp.open( bnk_filename.c_str() ); if( bnk_file ) { @@ -550,9 +536,6 @@ void CrolPlayer::load_instrument_events( binistream *f, CVoiceData &voice, binistream *bnk_file, SBnkHeader const &bnk_header ) { int16 const number_of_instrument_events = f->readInt( 2 ); - if (number_of_instrument_events<0) { - return; - } TInstrumentEvents &instrument_events = voice.instrument_events; @@ -564,7 +547,7 @@ void CrolPlayer::load_instrument_events( binistream *f, CVoiceData &voice, event.time = f->readInt( 2 ); f->readString( event.name, 9 ); - std::string event_name = event.name; + std::string event_name = event.name; event.ins_index = load_rol_instrument( bnk_file, bnk_header, event_name ); instrument_events.push_back( event ); @@ -578,9 +561,6 @@ void CrolPlayer::load_instrument_events( binistream *f, CVoiceData &voice, void CrolPlayer::load_volume_events( binistream *f, CVoiceData &voice ) { int16 const number_of_volume_events = f->readInt( 2 ); - if (number_of_volume_events<0) { - return; - } TVolumeEvents &volume_events = voice.volume_events; @@ -601,9 +581,6 @@ void CrolPlayer::load_volume_events( binistream *f, CVoiceData &voice ) void CrolPlayer::load_pitch_events( binistream *f, CVoiceData &voice ) { int16 const number_of_pitch_events = f->readInt( 2 ); - if (number_of_pitch_events<0) { - return; - } TPitchEvents &pitch_events = voice.pitch_events; @@ -689,7 +666,7 @@ int CrolPlayer::load_rol_instrument( binistream *f, SBnkHeader const &header, st else { // set up default instrument data here - memset( &usedIns.instrument, 0, sizeof(usedIns.instrument) ); + memset( &usedIns.instrument, 0, sizeof(SRolInstrument) ); } ins_list.push_back( usedIns ); @@ -700,7 +677,7 @@ int CrolPlayer::get_ins_index( std::string const &name ) const { for(unsigned int i=0; i<ins_list.size(); ++i) { - if( strcmp_nocase(ins_list[i].name.c_str(), name.c_str()) == 0 ) + if( strcasecmp(ins_list[i].name.c_str(), name.c_str()) == 0 ) { return i; } diff --git a/src/adplug/core/rol.h b/src/adplug/core/rol.h index 510efee..eed9c34 100644 --- a/src/adplug/core/rol.h +++ b/src/adplug/core/rol.h @@ -1,6 +1,6 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. - * Copyright (C) 1999 - 2004 Simon Peter, <dn.tlp@gmx.net>, et al. + * Copyright (C) 1999 - 2008 Simon Peter, <dn.tlp@gmx.net>, et al. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -25,11 +25,10 @@ #include <vector> #include <string> +#include <strings.h> #include "player.h" -#include <libaudcore/audstrings.h> - class CrolPlayer: public CPlayer { public: @@ -39,10 +38,10 @@ public: ~CrolPlayer(); - bool load (VFSFile &fd, const CFileProvider &fp); + bool load (const std::string &filename, const CFileProvider &fp); bool update (); - void rewind (int subsong); // rewinds to specified subsong - float getrefresh(); // returns needed timer refresh rate + void rewind (int subsong); // rewinds to specified subsong + float getrefresh(); // returns needed timer refresh rate std::string gettype() { return std::string("Adlib Visual Composer"); } @@ -271,7 +270,7 @@ private: private: bool keyLess( const char *const lhs, const char *const rhs ) const { - return strcmp_nocase(lhs, rhs) < 0; + return strcasecmp(lhs, rhs) < 0; } }; @@ -289,7 +288,7 @@ private: unsigned char bdRegister; unsigned char bxRegister[9]; unsigned char volumeCache[11]; - uint16 freqCache[11]; + uint16 freqCache[11]; real32 pitchCache[11]; static int const kSizeofDataRecord; diff --git a/src/adplug/core/s3m.cc b/src/adplug/core/s3m.cc index b8cc94c..1f626e2 100644 --- a/src/adplug/core/s3m.cc +++ b/src/adplug/core/s3m.cc @@ -22,324 +22,239 @@ * Extra Fine Slides (EEx, FEx) & Fine Vibrato (Uxy) are inaccurate */ -#include <string.h> - +#include <cstring> #include "s3m.h" -const signed char - Cs3mPlayer::chnresolv[] = // S3M -> adlib channel conversion -{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, - 4, 5, 6, 7, 8, -1, -1, -1, -1, -1, -1, -1 }; +const signed char Cs3mPlayer::chnresolv[] = // S3M -> adlib channel conversion + {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,2,3,4,5,6,7,8,-1,-1,-1,-1,-1,-1,-1}; -const unsigned short - Cs3mPlayer::notetable[12] = // S3M adlib note table -{ 340, 363, 385, 408, 432, 458, 485, 514, 544, 577, 611, 647 }; +const unsigned short Cs3mPlayer::notetable[12] = // S3M adlib note table + {340,363,385,408,432,458,485,514,544,577,611,647}; -const unsigned char - Cs3mPlayer::vibratotab[32] = // vibrato rate table -{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 16, 15, 14, 13, 12, - 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; +const unsigned char Cs3mPlayer::vibratotab[32] = // vibrato rate table + {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1}; /*** public methods *************************************/ -CPlayer * -Cs3mPlayer::factory (Copl * newopl) +CPlayer *Cs3mPlayer::factory(Copl *newopl) { - return new Cs3mPlayer (newopl); + return new Cs3mPlayer(newopl); } -Cs3mPlayer::Cs3mPlayer (Copl * newopl):CPlayer (newopl) +Cs3mPlayer::Cs3mPlayer(Copl *newopl): CPlayer(newopl) { - int - i, - j, - k; - - memset (pattern, 255, sizeof (pattern)); - memset (orders, 255, sizeof (orders)); - - for (i = 0; i < 99; i++) // setup pattern - for (j = 0; j < 64; j++) - for (k = 0; k < 32; k++) - { + int i,j,k; + + memset(pattern,255,sizeof(pattern)); + memset(orders,255,sizeof(orders)); + + for(i=0;i<99;i++) // setup pattern + for(j=0;j<64;j++) + for(k=0;k<32;k++) { pattern[i][j][k].instrument = 0; pattern[i][j][k].info = 0; } } -bool -Cs3mPlayer::load (VFSFile & fd, const CFileProvider & fp) +bool Cs3mPlayer::load(const std::string &filename, const CFileProvider &fp) { - binistream *f = fp.open (fd); - if (!f) - return false; - unsigned short insptr[99], pattptr[99]; - int i, row; - unsigned char bufval, bufval2; - unsigned short ppatlen; - s3mheader *checkhead; - bool adlibins = false; + binistream *f = fp.open(filename); if(!f) return false; + unsigned short insptr[99],pattptr[99]; + int i,row; + unsigned char bufval,bufval2; + unsigned short ppatlen; + s3mheader *checkhead; + bool adlibins=false; // file validation section checkhead = new s3mheader; - load_header (f, checkhead); - if (checkhead->kennung != 0x1a || checkhead->typ != 16 - || checkhead->insnum > 99) - { - delete checkhead; - fp.close (f); - return false; - } - else if (strncmp (checkhead->scrm, "SCRM", 4)) - { - delete checkhead; - fp.close (f); - return false; - } - else - { // is an adlib module? - f->seek (checkhead->ordnum, binio::Add); - for (i = 0; i < checkhead->insnum; i++) - insptr[i] = f->readInt (2); - for (i = 0; i < checkhead->insnum; i++) - { - f->seek (insptr[i] * 16); - if (f->readInt (1) >= 2) - { - adlibins = true; - break; + load_header(f, checkhead); + if(checkhead->kennung != 0x1a || checkhead->typ != 16 + || checkhead->insnum > 99) { + delete checkhead; fp.close(f); return false; + } else + if(strncmp(checkhead->scrm,"SCRM",4)) { + delete checkhead; fp.close(f); return false; + } else { // is an adlib module? + f->seek(checkhead->ordnum, binio::Add); + for(i = 0; i < checkhead->insnum; i++) + insptr[i] = f->readInt(2); + for(i=0;i<checkhead->insnum;i++) { + f->seek(insptr[i]*16); + if(f->readInt(1) >= 2) { + adlibins = true; + break; + } } + delete checkhead; + if(!adlibins) { fp.close(f); return false; } } - delete checkhead; - if (!adlibins) - { - fp.close (f); - return false; - } - } // load section - f->seek (0); // rewind for load - load_header (f, &header); // read header + f->seek(0); // rewind for load + load_header(f, &header); // read header // security check - if (header.ordnum > 256 || header.insnum > 99 || header.patnum > 99) - { - fp.close (f); + if(header.ordnum > 256 || header.insnum > 99 || header.patnum > 99) { + fp.close(f); return false; } - for (i = 0; i < header.ordnum; i++) - orders[i] = f->readInt (1); // read orders - for (i = 0; i < header.insnum; i++) - insptr[i] = f->readInt (2); // instrument parapointers - for (i = 0; i < header.patnum; i++) - pattptr[i] = f->readInt (2); // pattern parapointers - - for (i = 0; i < header.insnum; i++) - { // load instruments - f->seek (insptr[i] * 16); - inst[i].type = f->readInt (1); - f->readString (inst[i].filename, 15); - inst[i].d00 = f->readInt (1); - inst[i].d01 = f->readInt (1); - inst[i].d02 = f->readInt (1); - inst[i].d03 = f->readInt (1); - inst[i].d04 = f->readInt (1); - inst[i].d05 = f->readInt (1); - inst[i].d06 = f->readInt (1); - inst[i].d07 = f->readInt (1); - inst[i].d08 = f->readInt (1); - inst[i].d09 = f->readInt (1); - inst[i].d0a = f->readInt (1); - inst[i].d0b = f->readInt (1); - inst[i].volume = f->readInt (1); - inst[i].dsk = f->readInt (1); - f->ignore (2); - inst[i].c2spd = f->readInt (4); - f->ignore (12); - f->readString (inst[i].name, 28); - f->readString (inst[i].scri, 4); + for(i = 0; i < header.ordnum; i++) orders[i] = f->readInt(1); // read orders + for(i = 0; i < header.insnum; i++) insptr[i] = f->readInt(2); // instrument parapointers + for(i = 0; i < header.patnum; i++) pattptr[i] = f->readInt(2); // pattern parapointers + + for(i=0;i<header.insnum;i++) { // load instruments + f->seek(insptr[i]*16); + inst[i].type = f->readInt(1); + f->readString(inst[i].filename, 15); + inst[i].d00 = f->readInt(1); inst[i].d01 = f->readInt(1); + inst[i].d02 = f->readInt(1); inst[i].d03 = f->readInt(1); + inst[i].d04 = f->readInt(1); inst[i].d05 = f->readInt(1); + inst[i].d06 = f->readInt(1); inst[i].d07 = f->readInt(1); + inst[i].d08 = f->readInt(1); inst[i].d09 = f->readInt(1); + inst[i].d0a = f->readInt(1); inst[i].d0b = f->readInt(1); + inst[i].volume = f->readInt(1); inst[i].dsk = f->readInt(1); + f->ignore(2); + inst[i].c2spd = f->readInt(4); + f->ignore(12); + f->readString(inst[i].name, 28); + f->readString(inst[i].scri, 4); } - for (i = 0; i < header.patnum; i++) - { // depack patterns - f->seek (pattptr[i] * 16); - ppatlen = f->readInt (2); - unsigned long pattpos = f->pos (); - for (row = 0; (row < 64) && (pattpos - pattptr[i] * 16 <= ppatlen); row++) - do - { - bufval = f->readInt (1); - if (bufval & 32) - { - bufval2 = f->readInt (1); + for(i=0;i<header.patnum;i++) { // depack patterns + f->seek(pattptr[i]*16); + ppatlen = f->readInt(2); + unsigned long pattpos = f->pos(); + for(row=0;(row<64) && (pattpos-pattptr[i]*16<=ppatlen);row++) + do { + bufval = f->readInt(1); + if(bufval & 32) { + bufval2 = f->readInt(1); pattern[i][row][bufval & 31].note = bufval2 & 15; pattern[i][row][bufval & 31].oct = (bufval2 & 240) >> 4; - pattern[i][row][bufval & 31].instrument = f->readInt (1); + pattern[i][row][bufval & 31].instrument = f->readInt(1); } - if (bufval & 64) - pattern[i][row][bufval & 31].volume = f->readInt (1); - if (bufval & 128) - { - pattern[i][row][bufval & 31].command = f->readInt (1); - pattern[i][row][bufval & 31].info = f->readInt (1); + if(bufval & 64) + pattern[i][row][bufval & 31].volume = f->readInt(1); + if(bufval & 128) { + pattern[i][row][bufval & 31].command = f->readInt(1); + pattern[i][row][bufval & 31].info = f->readInt(1); } - } while (bufval); + } while(bufval); } - fp.close (f); - rewind (0); - return true; // done + fp.close(f); + rewind(0); + return true; // done } -bool -Cs3mPlayer::update () +bool Cs3mPlayer::update() { - unsigned char pattbreak = 0, donote; // remember vars - unsigned char pattnr, chan, row, info; // cache vars - signed char realchan; + unsigned char pattbreak=0,donote; // remember vars + unsigned char pattnr,chan,row,info; // cache vars + signed char realchan; // effect handling (timer dependant) - for (realchan = 0; realchan < 9; realchan++) - { - info = channel[realchan].info; // fill infobyte cache - switch (channel[realchan].fx) - { + for(realchan=0; realchan<9; realchan++) { + info = channel[realchan].info; // fill infobyte cache + switch(channel[realchan].fx) { case 11: - case 12: - if (channel[realchan].fx == 11) // dual command: H00 and Dxy - vibrato (realchan, channel[realchan].dualinfo); - else // dual command: G00 and Dxy - tone_portamento (realchan, channel[realchan].dualinfo); - case 4: - if (info <= 0x0f) // volume slide down - { - if (channel[realchan].vol - info >= 0) - channel[realchan].vol -= info; - else - channel[realchan].vol = 0; + case 12: if(channel[realchan].fx == 11) // dual command: H00 and Dxy + vibrato(realchan,channel[realchan].dualinfo); + else // dual command: G00 and Dxy + tone_portamento(realchan,channel[realchan].dualinfo); + case 4: if(info <= 0x0f) { // volume slide down + if(channel[realchan].vol - info >= 0) + channel[realchan].vol -= info; + else + channel[realchan].vol = 0; } - if ((info & 0x0f) == 0) // volume slide up - { - if (channel[realchan].vol + (info >> 4) <= 63) + if((info & 0x0f) == 0) { // volume slide up + if(channel[realchan].vol + (info >> 4) <= 63) channel[realchan].vol += info >> 4; else channel[realchan].vol = 63; } - setvolume (realchan); + setvolume(realchan); break; - case 5: - if (info == 0xf0 || info <= 0xe0) - { // slide down - slide_down (realchan, info); - setfreq (realchan); - } + case 5: if(info == 0xf0 || info <= 0xe0) { // slide down + slide_down(realchan,info); + setfreq(realchan); + } break; - case 6: - if (info == 0xf0 || info <= 0xe0) - { // slide up - slide_up (realchan, info); - setfreq (realchan); - } + case 6: if(info == 0xf0 || info <= 0xe0) { // slide up + slide_up(realchan,info); + setfreq(realchan); + } break; - case 7: - tone_portamento (realchan, channel[realchan].dualinfo); - break; // tone portamento - case 8: - vibrato (realchan, channel[realchan].dualinfo); - break; // vibrato - case 10: - channel[realchan].nextfreq = channel[realchan].freq; // arpeggio + case 7: tone_portamento(realchan,channel[realchan].dualinfo); break; // tone portamento + case 8: vibrato(realchan,channel[realchan].dualinfo); break; // vibrato + case 10: channel[realchan].nextfreq = channel[realchan].freq; // arpeggio channel[realchan].nextoct = channel[realchan].oct; - switch (channel[realchan].trigger) - { - case 0: - channel[realchan].freq = notetable[channel[realchan].note]; - break; - case 1: - if (channel[realchan].note + ((info & 0xf0) >> 4) < 12) - channel[realchan].freq = - notetable[channel[realchan].note + ((info & 0xf0) >> 4)]; - else - { - channel[realchan].freq = - notetable[channel[realchan].note + ((info & 0xf0) >> 4) - 12]; - channel[realchan].oct++; - } + switch(channel[realchan].trigger) { + case 0: channel[realchan].freq = notetable[channel[realchan].note]; break; + case 1: if(channel[realchan].note + ((info & 0xf0) >> 4) < 12) + channel[realchan].freq = notetable[channel[realchan].note + ((info & 0xf0) >> 4)]; + else { + channel[realchan].freq = notetable[channel[realchan].note + ((info & 0xf0) >> 4) - 12]; + channel[realchan].oct++; + } break; - case 2: - if (channel[realchan].note + (info & 0x0f) < 12) - channel[realchan].freq = - notetable[channel[realchan].note + (info & 0x0f)]; - else - { - channel[realchan].freq = - notetable[channel[realchan].note + (info & 0x0f) - 12]; - channel[realchan].oct++; - } + case 2: if(channel[realchan].note + (info & 0x0f) < 12) + channel[realchan].freq = notetable[channel[realchan].note + (info & 0x0f)]; + else { + channel[realchan].freq = notetable[channel[realchan].note + (info & 0x0f) - 12]; + channel[realchan].oct++; + } break; } - if (channel[realchan].trigger < 2) + if(channel[realchan].trigger < 2) channel[realchan].trigger++; else channel[realchan].trigger = 0; - setfreq (realchan); + setfreq(realchan); channel[realchan].freq = channel[realchan].nextfreq; channel[realchan].oct = channel[realchan].nextoct; break; - case 21: - vibrato (realchan, (unsigned char) (info / 4)); - break; // fine vibrato + case 21: vibrato(realchan,(unsigned char) (info / 4)); break; // fine vibrato } } - if (del) - { // speed compensation + if(del) { // speed compensation del--; return !songend; } // arrangement handling pattnr = orders[ord]; - if (pattnr == 0xff || ord > header.ordnum) - { // "--" end of song - songend = 1; // set end-flag + if(pattnr == 0xff || ord > header.ordnum) { // "--" end of song + songend = 1; // set end-flag ord = 0; pattnr = orders[ord]; - if (pattnr == 0xff) + if(pattnr == 0xff) return !songend; } - if (pattnr == 0xfe) - { // "++" skip marker - ord++; - pattnr = orders[ord]; + if(pattnr == 0xfe) { // "++" skip marker + ord++; pattnr = orders[ord]; } // play row - row = crow; // fill row cache - for (chan = 0; chan < 32; chan++) - { - if (!(header.chanset[chan] & 128)) // resolve S3M -> AdLib channels + row = crow; // fill row cache + for(chan=0;chan<32;chan++) { + if(!(header.chanset[chan] & 128)) // resolve S3M -> AdLib channels realchan = chnresolv[header.chanset[chan] & 127]; else realchan = -1; // channel disabled - if (realchan != -1) - { // channel playable? + if(realchan != -1) { // channel playable? // set channel values donote = 0; - if (pattern[pattnr][row][chan].note < 14) - { + if(pattern[pattnr][row][chan].note < 14) { // tone portamento - if (pattern[pattnr][row][chan].command == 7 - || pattern[pattnr][row][chan].command == 12) - { - channel[realchan].nextfreq = - notetable[pattern[pattnr][row][chan].note]; + if(pattern[pattnr][row][chan].command == 7 || pattern[pattnr][row][chan].command == 12) { + channel[realchan].nextfreq = notetable[pattern[pattnr][row][chan].note]; channel[realchan].nextoct = pattern[pattnr][row][chan].oct; - } - else - { // normal note + } else { // normal note channel[realchan].note = pattern[pattnr][row][chan].note; channel[realchan].freq = notetable[pattern[pattnr][row][chan].note]; channel[realchan].oct = pattern[pattnr][row][chan].oct; @@ -347,51 +262,43 @@ Cs3mPlayer::update () donote = 1; } } - if (pattern[pattnr][row][chan].note == 14) - { // key off (is 14 here, cause note is only first 4 bits) + if(pattern[pattnr][row][chan].note == 14) { // key off (is 14 here, cause note is only first 4 bits) channel[realchan].key = 0; - setfreq (realchan); + setfreq(realchan); } - if ((channel[realchan].fx != 8 && channel[realchan].fx != 11) && // vibrato begins - (pattern[pattnr][row][chan].command == 8 - || pattern[pattnr][row][chan].command == 11)) - { + if((channel[realchan].fx != 8 && channel[realchan].fx != 11) && // vibrato begins + (pattern[pattnr][row][chan].command == 8 || pattern[pattnr][row][chan].command == 11)) { channel[realchan].nextfreq = channel[realchan].freq; channel[realchan].nextoct = channel[realchan].oct; } - if (pattern[pattnr][row][chan].note >= 14) - if ((channel[realchan].fx == 8 || channel[realchan].fx == 11) && // vibrato ends - (pattern[pattnr][row][chan].command != 8 - && pattern[pattnr][row][chan].command != 11)) - { + if(pattern[pattnr][row][chan].note >= 14) + if((channel[realchan].fx == 8 || channel[realchan].fx == 11) && // vibrato ends + (pattern[pattnr][row][chan].command != 8 && pattern[pattnr][row][chan].command != 11)) { channel[realchan].freq = channel[realchan].nextfreq; channel[realchan].oct = channel[realchan].nextoct; - setfreq (realchan); + setfreq(realchan); } - if (pattern[pattnr][row][chan].instrument) - { // set instrument + if(pattern[pattnr][row][chan].instrument) { // set instrument channel[realchan].inst = pattern[pattnr][row][chan].instrument - 1; - if (inst[channel[realchan].inst].volume < 64) + if(inst[channel[realchan].inst].volume < 64) channel[realchan].vol = inst[channel[realchan].inst].volume; else channel[realchan].vol = 63; - if (pattern[pattnr][row][chan].command != 7) + if(pattern[pattnr][row][chan].command != 7) donote = 1; } - if (pattern[pattnr][row][chan].volume != 255) - { - if (pattern[pattnr][row][chan].volume < 64) // set volume + if(pattern[pattnr][row][chan].volume != 255) { + if(pattern[pattnr][row][chan].volume < 64) // set volume channel[realchan].vol = pattern[pattnr][row][chan].volume; else channel[realchan].vol = 63; } - channel[realchan].fx = pattern[pattnr][row][chan].command; // set command - if (pattern[pattnr][row][chan].info) // set infobyte + channel[realchan].fx = pattern[pattnr][row][chan].command; // set command + if(pattern[pattnr][row][chan].info) // set infobyte channel[realchan].info = pattern[pattnr][row][chan].info; // some commands reset the infobyte memory - switch (channel[realchan].fx) - { + switch(channel[realchan].fx) { case 1: case 2: case 3: @@ -401,117 +308,81 @@ Cs3mPlayer::update () } // play note - if (donote) - playnote (realchan); - if (pattern[pattnr][row][chan].volume != 255) // set volume - setvolume (realchan); + if(donote) + playnote(realchan); + if(pattern[pattnr][row][chan].volume != 255) // set volume + setvolume(realchan); // command handling (row dependant) info = channel[realchan].info; // fill infobyte cache - switch (channel[realchan].fx) - { - case 1: - speed = info; - break; // set speed - case 2: - if (info <= ord) - songend = 1; - ord = info; - crow = 0; - pattbreak = 1; - break; // jump to order - case 3: - if (!pattbreak) - { - crow = info; - ord++; - pattbreak = 1; - } - break; // pattern break - case 4: - if (info > 0xf0) // fine volume down - { - if (channel[realchan].vol - (info & 0x0f) >= 0) - channel[realchan].vol -= info & 0x0f; - else - channel[realchan].vol = 0; + switch(channel[realchan].fx) { + case 1: speed = info; break; // set speed + case 2: if(info <= ord) songend = 1; ord = info; crow = 0; pattbreak = 1; break; // jump to order + case 3: if(!pattbreak) { crow = info; ord++; pattbreak = 1; } break; // pattern break + case 4: if(info > 0xf0) { // fine volume down + if(channel[realchan].vol - (info & 0x0f) >= 0) + channel[realchan].vol -= info & 0x0f; + else + channel[realchan].vol = 0; } - if ((info & 0x0f) == 0x0f && info >= 0x1f) // fine volume up - { - if (channel[realchan].vol + ((info & 0xf0) >> 4) <= 63) + if((info & 0x0f) == 0x0f && info >= 0x1f) { // fine volume up + if(channel[realchan].vol + ((info & 0xf0) >> 4) <= 63) channel[realchan].vol += (info & 0xf0) >> 4; else channel[realchan].vol = 63; } - setvolume (realchan); + setvolume(realchan); break; - case 5: - if (info > 0xf0) - { // fine slide down - slide_down (realchan, (unsigned char) (info & 0x0f)); - setfreq (realchan); - } - if (info > 0xe0 && info < 0xf0) - { // extra fine slide down - slide_down (realchan, (unsigned char) ((info & 0x0f) / 4)); - setfreq (realchan); + case 5: if(info > 0xf0) { // fine slide down + slide_down(realchan,(unsigned char) (info & 0x0f)); + setfreq(realchan); + } + if(info > 0xe0 && info < 0xf0) { // extra fine slide down + slide_down(realchan,(unsigned char) ((info & 0x0f) / 4)); + setfreq(realchan); } break; - case 6: - if (info > 0xf0) - { // fine slide up - slide_up (realchan, (unsigned char) (info & 0x0f)); - setfreq (realchan); - } - if (info > 0xe0 && info < 0xf0) - { // extra fine slide up - slide_up (realchan, (unsigned char) ((info & 0x0f) / 4)); - setfreq (realchan); + case 6: if(info > 0xf0) { // fine slide up + slide_up(realchan,(unsigned char) (info & 0x0f)); + setfreq(realchan); + } + if(info > 0xe0 && info < 0xf0) { // extra fine slide up + slide_up(realchan,(unsigned char) ((info & 0x0f) / 4)); + setfreq(realchan); } break; - case 7: // tone portamento - case 8: - if ((channel[realchan].fx == 7 || // vibrato (remember info for dual commands) - channel[realchan].fx == 8) && pattern[pattnr][row][chan].info) - channel[realchan].dualinfo = info; + case 7: // tone portamento + case 8: if((channel[realchan].fx == 7 || // vibrato (remember info for dual commands) + channel[realchan].fx == 8) && pattern[pattnr][row][chan].info) + channel[realchan].dualinfo = info; break; - case 10: - channel[realchan].trigger = 0; - break; // arpeggio (set trigger) - case 19: - if (info == 0xb0) // set loop start - loopstart = row; - if (info > 0xb0 && info <= 0xbf) // pattern loop - { - if (!loopcnt) - { + case 10: channel[realchan].trigger = 0; break; // arpeggio (set trigger) + case 19: if(info == 0xb0) // set loop start + loopstart = row; + if(info > 0xb0 && info <= 0xbf) { // pattern loop + if(!loopcnt) { loopcnt = info & 0x0f; crow = loopstart; pattbreak = 1; - } - else if (--loopcnt > 0) - { - crow = loopstart; - pattbreak = 1; - } + } else + if(--loopcnt > 0) { + crow = loopstart; + pattbreak = 1; + } } - if ((info & 0xf0) == 0xe0) // patterndelay + if((info & 0xf0) == 0xe0) // patterndelay del = speed * (info & 0x0f) - 1; break; - case 20: - tempo = info; - break; // set tempo + case 20: tempo = info; break; // set tempo } } } - if (!del) + if(!del) del = speed - 1; // speed compensation - if (!pattbreak) - { // next row (only if no manual advance) + if(!pattbreak) { // next row (only if no manual advance) crow++; - if (crow > 63) - { + if(crow > 63) { crow = 0; ord++; loopstart = 0; @@ -521,208 +392,152 @@ Cs3mPlayer::update () return !songend; // still playing } -void -Cs3mPlayer::rewind (int subsong) +void Cs3mPlayer::rewind(int subsong) { // set basic variables - songend = 0; - ord = 0; - crow = 0; - tempo = header.it; - speed = header.is; - del = 0; - loopstart = 0; - loopcnt = 0; - - memset (channel, 0, sizeof (channel)); - - opl->init (); // reset OPL chip - opl->write (1, 32); // Go to ym3812 mode + songend = 0; ord = 0; crow = 0; tempo = header.it; + speed = header.is; del = 0; loopstart = 0; loopcnt = 0; + + memset(channel,0,sizeof(channel)); + + opl->init(); // reset OPL chip + opl->write(1,32); // Go to ym3812 mode } -std::string Cs3mPlayer::gettype () +std::string Cs3mPlayer::gettype() { - char - filever[5]; - - switch (header.cwtv) - { // determine version number - case 0x1300: - strcpy (filever, "3.00"); - break; - case 0x1301: - strcpy (filever, "3.01"); - break; - case 0x1303: - strcpy (filever, "3.03"); - break; - case 0x1320: - strcpy (filever, "3.20"); - break; - default: - strcpy (filever, "3.??"); + char filever[5]; + + switch(header.cwtv) { // determine version number + case 0x1300: strcpy(filever,"3.00"); break; + case 0x1301: strcpy(filever,"3.01"); break; + case 0x1303: strcpy(filever,"3.03"); break; + case 0x1320: strcpy(filever,"3.20"); break; + default: strcpy(filever,"3.??"); } - return (std::string ("Scream Tracker ") + filever); + return (std::string("Scream Tracker ") + filever); } -float -Cs3mPlayer::getrefresh () +float Cs3mPlayer::getrefresh() { return (float) (tempo / 2.5); } /*** private methods *************************************/ -void -Cs3mPlayer::load_header (binistream * f, s3mheader * h) +void Cs3mPlayer::load_header(binistream *f, s3mheader *h) { int i; - f->readString (h->name, 28); - h->kennung = f->readInt (1); - h->typ = f->readInt (1); - f->ignore (2); - h->ordnum = f->readInt (2); - h->insnum = f->readInt (2); - h->patnum = f->readInt (2); - h->flags = f->readInt (2); - h->cwtv = f->readInt (2); - h->ffi = f->readInt (2); - f->readString (h->scrm, 4); - h->gv = f->readInt (1); - h->is = f->readInt (1); - h->it = f->readInt (1); - h->mv = f->readInt (1); - h->uc = f->readInt (1); - h->dp = f->readInt (1); - f->ignore (8); - h->special = f->readInt (2); - for (i = 0; i < 32; i++) - h->chanset[i] = f->readInt (1); + f->readString(h->name, 28); + h->kennung = f->readInt(1); h->typ = f->readInt(1); + f->ignore(2); + h->ordnum = f->readInt(2); h->insnum = f->readInt(2); + h->patnum = f->readInt(2); h->flags = f->readInt(2); + h->cwtv = f->readInt(2); h->ffi = f->readInt(2); + f->readString(h->scrm, 4); + h->gv = f->readInt(1); h->is = f->readInt(1); h->it = f->readInt(1); + h->mv = f->readInt(1); h->uc = f->readInt(1); h->dp = f->readInt(1); + f->ignore(8); + h->special = f->readInt(2); + for(i = 0; i < 32; i++) h->chanset[i] = f->readInt(1); } -void -Cs3mPlayer::setvolume (unsigned char chan) +void Cs3mPlayer::setvolume(unsigned char chan) { unsigned char op = op_table[chan], insnr = channel[chan].inst; - opl->write (0x43 + op, - (int) (63 - - ((63 - - (inst[insnr].d03 & 63)) / 63.0) * channel[chan].vol) + - (inst[insnr].d03 & 192)); - if (inst[insnr].d0a & 1) - opl->write (0x40 + op, - (int) (63 - - ((63 - - (inst[insnr].d02 & 63)) / 63.0) * - channel[chan].vol) + (inst[insnr].d02 & 192)); + opl->write(0x43 + op,(int)(63-((63-(inst[insnr].d03 & 63))/63.0)*channel[chan].vol) + (inst[insnr].d03 & 192)); + if(inst[insnr].d0a & 1) + opl->write(0x40 + op,(int)(63-((63-(inst[insnr].d02 & 63))/63.0)*channel[chan].vol) + (inst[insnr].d02 & 192)); } -void -Cs3mPlayer::setfreq (unsigned char chan) +void Cs3mPlayer::setfreq(unsigned char chan) { - opl->write (0xa0 + chan, channel[chan].freq & 255); - if (channel[chan].key) - opl->write (0xb0 + chan, - (((channel[chan].freq & 768) >> 8) + - (channel[chan].oct << 2)) | 32); + opl->write(0xa0 + chan, channel[chan].freq & 255); + if(channel[chan].key) + opl->write(0xb0 + chan, (((channel[chan].freq & 768) >> 8) + (channel[chan].oct << 2)) | 32); else - opl->write (0xb0 + chan, - ((channel[chan].freq & 768) >> 8) + (channel[chan].oct << 2)); + opl->write(0xb0 + chan, ((channel[chan].freq & 768) >> 8) + (channel[chan].oct << 2)); } -void -Cs3mPlayer::playnote (unsigned char chan) +void Cs3mPlayer::playnote(unsigned char chan) { unsigned char op = op_table[chan], insnr = channel[chan].inst; - opl->write (0xb0 + chan, 0); // stop old note + opl->write(0xb0 + chan, 0); // stop old note // set instrument data - opl->write (0x20 + op, inst[insnr].d00); - opl->write (0x23 + op, inst[insnr].d01); - opl->write (0x40 + op, inst[insnr].d02); - opl->write (0x43 + op, inst[insnr].d03); - opl->write (0x60 + op, inst[insnr].d04); - opl->write (0x63 + op, inst[insnr].d05); - opl->write (0x80 + op, inst[insnr].d06); - opl->write (0x83 + op, inst[insnr].d07); - opl->write (0xe0 + op, inst[insnr].d08); - opl->write (0xe3 + op, inst[insnr].d09); - opl->write (0xc0 + chan, inst[insnr].d0a); + opl->write(0x20 + op, inst[insnr].d00); + opl->write(0x23 + op, inst[insnr].d01); + opl->write(0x40 + op, inst[insnr].d02); + opl->write(0x43 + op, inst[insnr].d03); + opl->write(0x60 + op, inst[insnr].d04); + opl->write(0x63 + op, inst[insnr].d05); + opl->write(0x80 + op, inst[insnr].d06); + opl->write(0x83 + op, inst[insnr].d07); + opl->write(0xe0 + op, inst[insnr].d08); + opl->write(0xe3 + op, inst[insnr].d09); + opl->write(0xc0 + chan, inst[insnr].d0a); // set frequency & play channel[chan].key = 1; - setfreq (chan); + setfreq(chan); } -void -Cs3mPlayer::slide_down (unsigned char chan, unsigned char amount) +void Cs3mPlayer::slide_down(unsigned char chan, unsigned char amount) { - if (channel[chan].freq - amount > 340) + if(channel[chan].freq - amount > 340) channel[chan].freq -= amount; - else if (channel[chan].oct > 0) - { - channel[chan].oct--; - channel[chan].freq = 684; - } else - channel[chan].freq = 340; + if(channel[chan].oct > 0) { + channel[chan].oct--; + channel[chan].freq = 684; + } else + channel[chan].freq = 340; } -void -Cs3mPlayer::slide_up (unsigned char chan, unsigned char amount) +void Cs3mPlayer::slide_up(unsigned char chan, unsigned char amount) { - if (channel[chan].freq + amount < 686) + if(channel[chan].freq + amount < 686) channel[chan].freq += amount; - else if (channel[chan].oct < 7) - { - channel[chan].oct++; - channel[chan].freq = 341; - } else - channel[chan].freq = 686; + if(channel[chan].oct < 7) { + channel[chan].oct++; + channel[chan].freq = 341; + } else + channel[chan].freq = 686; } -void -Cs3mPlayer::vibrato (unsigned char chan, unsigned char info) +void Cs3mPlayer::vibrato(unsigned char chan, unsigned char info) { - unsigned char i, speed, depth; + unsigned char i,speed,depth; speed = info >> 4; depth = (info & 0x0f) / 2; - for (i = 0; i < speed; i++) - { + for(i=0;i<speed;i++) { channel[chan].trigger++; - while (channel[chan].trigger >= 64) + while(channel[chan].trigger >= 64) channel[chan].trigger -= 64; - if (channel[chan].trigger >= 16 && channel[chan].trigger < 48) - slide_down (chan, - (unsigned char) (vibratotab[channel[chan].trigger - 16] / - (16 - depth))); - if (channel[chan].trigger < 16) - slide_up (chan, - (unsigned char) (vibratotab[channel[chan].trigger + 16] / - (16 - depth))); - if (channel[chan].trigger >= 48) - slide_up (chan, - (unsigned char) (vibratotab[channel[chan].trigger - 48] / - (16 - depth))); + if(channel[chan].trigger >= 16 && channel[chan].trigger < 48) + slide_down(chan,(unsigned char) (vibratotab[channel[chan].trigger - 16] / (16-depth))); + if(channel[chan].trigger < 16) + slide_up(chan,(unsigned char) (vibratotab[channel[chan].trigger + 16] / (16-depth))); + if(channel[chan].trigger >= 48) + slide_up(chan,(unsigned char) (vibratotab[channel[chan].trigger - 48] / (16-depth))); } - setfreq (chan); + setfreq(chan); } -void -Cs3mPlayer::tone_portamento (unsigned char chan, unsigned char info) +void Cs3mPlayer::tone_portamento(unsigned char chan, unsigned char info) { - if (channel[chan].freq + (channel[chan].oct << 10) < - channel[chan].nextfreq + (channel[chan].nextoct << 10)) - slide_up (chan, info); - if (channel[chan].freq + (channel[chan].oct << 10) > - channel[chan].nextfreq + (channel[chan].nextoct << 10)) - slide_down (chan, info); - setfreq (chan); + if(channel[chan].freq + (channel[chan].oct << 10) < channel[chan].nextfreq + + (channel[chan].nextoct << 10)) + slide_up(chan,info); + if(channel[chan].freq + (channel[chan].oct << 10) > channel[chan].nextfreq + + (channel[chan].nextoct << 10)) + slide_down(chan,info); + setfreq(chan); } diff --git a/src/adplug/core/s3m.h b/src/adplug/core/s3m.h index bee1a94..1c95c42 100644 --- a/src/adplug/core/s3m.h +++ b/src/adplug/core/s3m.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. - * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * Copyright (C) 1999 - 2006 Simon Peter, <dn.tlp@gmx.net>, et al. + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -26,82 +26,82 @@ class Cs3mPlayer: public CPlayer { -public: + public: static CPlayer *factory(Copl *newopl); - Cs3mPlayer(Copl *newopl); + Cs3mPlayer(Copl *newopl); - bool load(VFSFile &fd, const CFileProvider &fp); - bool update(); - void rewind(int subsong); - float getrefresh(); + bool load(const std::string &filename, const CFileProvider &fp); + bool update(); + void rewind(int subsong); + float getrefresh(); - std::string gettype(); - std::string gettitle() - { return std::string(header.name); }; + std::string gettype(); + std::string gettitle() + { return std::string(header.name); }; - unsigned int getpatterns() - { return header.patnum; }; - unsigned int getpattern() - { return orders[ord]; }; - unsigned int getorders() - { return (header.ordnum-1); }; - unsigned int getorder() - { return ord; }; - unsigned int getrow() - { return crow; }; - unsigned int getspeed() - { return speed; }; - unsigned int getinstruments() - { return header.insnum; }; - std::string getinstrument(unsigned int n) - { return std::string(inst[n].name); }; + unsigned int getpatterns() + { return header.patnum; }; + unsigned int getpattern() + { return orders[ord]; }; + unsigned int getorders() + { return (header.ordnum-1); }; + unsigned int getorder() + { return ord; }; + unsigned int getrow() + { return crow; }; + unsigned int getspeed() + { return speed; }; + unsigned int getinstruments() + { return header.insnum; }; + std::string getinstrument(unsigned int n) + { return std::string(inst[n].name); }; -protected: - struct s3mheader { - char name[28]; // song name - unsigned char kennung,typ,dummy[2]; - unsigned short ordnum,insnum,patnum,flags,cwtv,ffi; - char scrm[4]; - unsigned char gv,is,it,mv,uc,dp,dummy2[8]; - unsigned short special; - unsigned char chanset[32]; - }; + protected: + struct s3mheader { + char name[28]; // song name + unsigned char kennung,typ,dummy[2]; + unsigned short ordnum,insnum,patnum,flags,cwtv,ffi; + char scrm[4]; + unsigned char gv,is,it,mv,uc,dp,dummy2[8]; + unsigned short special; + unsigned char chanset[32]; + }; - struct s3minst { - unsigned char type; - char filename[15]; - unsigned char d00,d01,d02,d03,d04,d05,d06,d07,d08,d09,d0a,d0b,volume,dsk,dummy[2]; - unsigned long c2spd; - char dummy2[12], name[28],scri[4]; - } inst[99]; + struct s3minst { + unsigned char type; + char filename[15]; + unsigned char d00,d01,d02,d03,d04,d05,d06,d07,d08,d09,d0a,d0b,volume,dsk,dummy[2]; + unsigned long c2spd; + char dummy2[12], name[28],scri[4]; + } inst[99]; - struct { - unsigned char note,oct,instrument,volume,command,info; - } pattern[99][64][32]; + struct { + unsigned char note,oct,instrument,volume,command,info; + } pattern[99][64][32]; - struct { - unsigned short freq,nextfreq; - unsigned char oct,vol,inst,fx,info,dualinfo,key,nextoct,trigger,note; - } channel[9]; + struct { + unsigned short freq,nextfreq; + unsigned char oct,vol,inst,fx,info,dualinfo,key,nextoct,trigger,note; + } channel[9]; - s3mheader header; - unsigned char orders[256]; - unsigned char crow,ord,speed,tempo,del,songend,loopstart,loopcnt; + s3mheader header; + unsigned char orders[256]; + unsigned char crow,ord,speed,tempo,del,songend,loopstart,loopcnt; -private: - static const signed char chnresolv[]; - static const unsigned short notetable[12]; - static const unsigned char vibratotab[32]; + private: + static const signed char chnresolv[]; + static const unsigned short notetable[12]; + static const unsigned char vibratotab[32]; - void load_header(binistream *f, s3mheader *h); - void setvolume(unsigned char chan); - void setfreq(unsigned char chan); - void playnote(unsigned char chan); - void slide_down(unsigned char chan, unsigned char amount); - void slide_up(unsigned char chan, unsigned char amount); - void vibrato(unsigned char chan, unsigned char info); - void tone_portamento(unsigned char chan, unsigned char info); + void load_header(binistream *f, s3mheader *h); + void setvolume(unsigned char chan); + void setfreq(unsigned char chan); + void playnote(unsigned char chan); + void slide_down(unsigned char chan, unsigned char amount); + void slide_up(unsigned char chan, unsigned char amount); + void vibrato(unsigned char chan, unsigned char info); + void tone_portamento(unsigned char chan, unsigned char info); }; #endif diff --git a/src/adplug/core/sa2.cc b/src/adplug/core/sa2.cc index b1c80e6..ee74f2b 100644 --- a/src/adplug/core/sa2.cc +++ b/src/adplug/core/sa2.cc @@ -1,6 +1,6 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. - * Copyright (C) 1999 - 2007 Simon Peter, <dn.tlp@gmx.net>, et al. + * Copyright (C) 1999 - 2008 Simon Peter, <dn.tlp@gmx.net>, et al. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -20,35 +20,29 @@ * SAdT Loader by Mamiya <mamiya@users.sourceforge.net> */ +#include <cstring> #include <stdio.h> #include <string.h> #include "sa2.h" #include "debug.h" -CPlayer * -Csa2Loader::factory (Copl * newopl) +CPlayer *Csa2Loader::factory(Copl *newopl) { - return new Csa2Loader (newopl); + return new Csa2Loader(newopl); } -bool -Csa2Loader::load (VFSFile & fd, const CFileProvider & fp) +bool Csa2Loader::load(const std::string &filename, const CFileProvider &fp) { - binistream *f = fp.open (fd); - if (!f) - return false; - struct - { - unsigned char data[11], arpstart, arpspeed, arppos, arpspdcnt; + binistream *f = fp.open(filename); if(!f) return false; + struct { + unsigned char data[11],arpstart,arpspeed,arppos,arpspdcnt; } insts; unsigned char buf; - int i, j, k, notedis = 0; - const unsigned char convfx[16] = - { 0, 1, 2, 3, 4, 5, 6, 255, 8, 255, 10, 11, 12, 13, 255, 15 }; + int i,j, k, notedis = 0; + const unsigned char convfx[16] = {0,1,2,3,4,5,6,255,8,255,10,11,12,13,255,15}; unsigned char sat_type; - enum SAT_TYPE - { + enum SAT_TYPE { HAS_ARPEGIOLIST = (1 << 7), HAS_V7PATTERNS = (1 << 6), HAS_ACTIVECHANNELS = (1 << 5), @@ -60,17 +54,12 @@ Csa2Loader::load (VFSFile & fd, const CFileProvider & fp) }; // read header - f->readString (header.sadt, 4); - header.version = f->readInt (1); + f->readString(header.sadt, 4); + header.version = f->readInt(1); // file validation section - if (strncmp (header.sadt, "SAdT", 4)) - { - fp.close (f); - return false; - } - switch (header.version) - { + if(strncmp(header.sadt,"SAdT",4)) { fp.close(f); return false; } + switch(header.version) { case 1: notedis = +0x18; sat_type = HAS_UNKNOWN127 | HAS_OLDPATTERNS | HAS_OLDBPM; @@ -101,214 +90,174 @@ Csa2Loader::load (VFSFile & fd, const CFileProvider & fp) sat_type = HAS_ARPEGIO | HAS_ARPEGIOLIST | HAS_TRACKORDER; break; case 9: - sat_type = - HAS_ARPEGIO | HAS_ARPEGIOLIST | HAS_TRACKORDER | HAS_ACTIVECHANNELS; + sat_type = HAS_ARPEGIO | HAS_ARPEGIOLIST | HAS_TRACKORDER | HAS_ACTIVECHANNELS; break; - default: /* unknown */ - fp.close (f); + default: /* unknown */ + fp.close(f); return false; } // load section // instruments - for (i = 0; i < 31; i++) - { - if (sat_type & HAS_ARPEGIO) - { - for (j = 0; j < 11; j++) - insts.data[j] = f->readInt (1); - insts.arpstart = f->readInt (1); - insts.arpspeed = f->readInt (1); - insts.arppos = f->readInt (1); - insts.arpspdcnt = f->readInt (1); + for(i = 0; i < 31; i++) { + if(sat_type & HAS_ARPEGIO) { + for(j = 0; j < 11; j++) insts.data[j] = f->readInt(1); + insts.arpstart = f->readInt(1); + insts.arpspeed = f->readInt(1); + insts.arppos = f->readInt(1); + insts.arpspdcnt = f->readInt(1); inst[i].arpstart = insts.arpstart; inst[i].arpspeed = insts.arpspeed; inst[i].arppos = insts.arppos; inst[i].arpspdcnt = insts.arpspdcnt; - } - else - { - for (j = 0; j < 11; j++) - insts.data[j] = f->readInt (1); + } else { + for(j = 0; j < 11; j++) insts.data[j] = f->readInt(1); inst[i].arpstart = 0; inst[i].arpspeed = 0; inst[i].arppos = 0; inst[i].arpspdcnt = 0; } - for (j = 0; j < 11; j++) + for(j=0;j<11;j++) inst[i].data[j] = insts.data[j]; inst[i].misc = 0; inst[i].slide = 0; } // instrument names - for (i = 0; i < 29; i++) - f->readString (instname[i], 17); + for(i = 0; i < 29; i++) f->readString(instname[i], 17); - f->ignore (3); // dummy bytes - for (i = 0; i < 128; i++) - order[i] = f->readInt (1); // pattern orders - if (sat_type & HAS_UNKNOWN127) - f->ignore (127); + f->ignore(3); // dummy bytes + for(i = 0; i < 128; i++) order[i] = f->readInt(1); // pattern orders + if(sat_type & HAS_UNKNOWN127) f->ignore(127); // infos - nop = f->readInt (2); - length = f->readInt (1); - restartpos = f->readInt (1); + nop = f->readInt(2); length = f->readInt(1); restartpos = f->readInt(1); // bpm - bpm = f->readInt (2); - if (sat_type & HAS_OLDBPM) - { - bpm = bpm * 125 / 50; // cps -> bpm + bpm = f->readInt(2); + if(sat_type & HAS_OLDBPM) { + bpm = bpm * 125 / 50; // cps -> bpm } - if (sat_type & HAS_ARPEGIOLIST) - { - init_specialarp (); - for (i = 0; i < 256; i++) - arplist[i] = f->readInt (1); // arpeggio list - for (i = 0; i < 256; i++) - arpcmd[i] = f->readInt (1); // arpeggio commands + if(sat_type & HAS_ARPEGIOLIST) { + init_specialarp(); + for(i = 0; i < 256; i++) arplist[i] = f->readInt(1); // arpeggio list + for(i = 0; i < 256; i++) arpcmd[i] = f->readInt(1); // arpeggio commands } - for (i = 0; i < 64; i++) - { // track orders - for (j = 0; j < 9; j++) - { - if (sat_type & HAS_TRACKORDER) - trackord[i][j] = f->readInt (1); + for(i=0;i<64;i++) { // track orders + for(j=0;j<9;j++) { + if(sat_type & HAS_TRACKORDER) + trackord[i][j] = f->readInt(1); else - { - trackord[i][j] = i * 9 + j; - } + { + trackord[i][j] = i * 9 + j; + } } } - if (sat_type & HAS_ACTIVECHANNELS) - activechan = f->readInt (2) << 16; // active channels + if(sat_type & HAS_ACTIVECHANNELS) + activechan = f->readInt(2) << 16; // active channels - AdPlug_LogWrite ("Csa2Loader::load(\"%s\"): sat_type = %x, nop = %d, " - "length = %d, restartpos = %d, activechan = %x, bpm = %d\n", - fd.filename (), sat_type, nop, length, restartpos, activechan, - bpm); + AdPlug_LogWrite("Csa2Loader::load(\"%s\"): sat_type = %x, nop = %d, " + "length = %d, restartpos = %d, activechan = %x, bpm = %d\n", + filename.c_str(), sat_type, nop, length, restartpos, activechan, bpm); // track data - if (sat_type & HAS_OLDPATTERNS) - { + if(sat_type & HAS_OLDPATTERNS) { i = 0; - while (!f->ateof ()) - { - for (j = 0; j < 64; j++) - { - for (k = 0; k < 9; k++) - { - buf = f->readInt (1); - tracks[i + k][j].note = buf ? (buf + notedis) : 0; - tracks[i + k][j].inst = f->readInt (1); - tracks[i + k][j].command = convfx[f->readInt (1) & 0xf]; - tracks[i + k][j].param1 = f->readInt (1); - tracks[i + k][j].param2 = f->readInt (1); + while(!f->ateof()) { + for(j=0;j<64;j++) { + for(k=0;k<9;k++) { + buf = f->readInt(1); + tracks[i+k][j].note = buf ? (buf + notedis) : 0; + tracks[i+k][j].inst = f->readInt(1); + tracks[i+k][j].command = convfx[f->readInt(1) & 0xf]; + tracks[i+k][j].param1 = f->readInt(1); + tracks[i+k][j].param2 = f->readInt(1); } } - i += 9; + i+=9; } - } - else if (sat_type & HAS_V7PATTERNS) - { - i = 0; - while (!f->ateof ()) - { - for (j = 0; j < 64; j++) - { - for (k = 0; k < 9; k++) - { - buf = f->readInt (1); - tracks[i + k][j].note = buf >> 1; - tracks[i + k][j].inst = (buf & 1) << 4; - buf = f->readInt (1); - tracks[i + k][j].inst += buf >> 4; - tracks[i + k][j].command = convfx[buf & 0x0f]; - buf = f->readInt (1); - tracks[i + k][j].param1 = buf >> 4; - tracks[i + k][j].param2 = buf & 0x0f; + } else + if(sat_type & HAS_V7PATTERNS) { + i = 0; + while(!f->ateof()) { + for(j=0;j<64;j++) { + for(k=0;k<9;k++) { + buf = f->readInt(1); + tracks[i+k][j].note = buf >> 1; + tracks[i+k][j].inst = (buf & 1) << 4; + buf = f->readInt(1); + tracks[i+k][j].inst += buf >> 4; + tracks[i+k][j].command = convfx[buf & 0x0f]; + buf = f->readInt(1); + tracks[i+k][j].param1 = buf >> 4; + tracks[i+k][j].param2 = buf & 0x0f; + } } + i+=9; } - i += 9; - } - } - else - { - i = 0; - while (!f->ateof ()) - { - for (j = 0; j < 64; j++) - { - buf = f->readInt (1); - tracks[i][j].note = buf >> 1; - tracks[i][j].inst = (buf & 1) << 4; - buf = f->readInt (1); - tracks[i][j].inst += buf >> 4; - tracks[i][j].command = convfx[buf & 0x0f]; - buf = f->readInt (1); - tracks[i][j].param1 = buf >> 4; - tracks[i][j].param2 = buf & 0x0f; + } else { + i = 0; + while(!f->ateof()) { + for(j=0;j<64;j++) { + buf = f->readInt(1); + tracks[i][j].note = buf >> 1; + tracks[i][j].inst = (buf & 1) << 4; + buf = f->readInt(1); + tracks[i][j].inst += buf >> 4; + tracks[i][j].command = convfx[buf & 0x0f]; + buf = f->readInt(1); + tracks[i][j].param1 = buf >> 4; + tracks[i][j].param2 = buf & 0x0f; + } + i++; } - i++; } - } - fp.close (f); + fp.close(f); // fix instrument names - for (i = 0; i < 29; i++) - for (j = 0; j < 17; j++) - if (!instname[i][j]) + for(i=0;i<29;i++) + for(j=0;j<17;j++) + if(!instname[i][j]) instname[i][j] = ' '; - rewind (0); // rewind module + rewind(0); // rewind module return true; } -std::string Csa2Loader::gettype () +std::string Csa2Loader::gettype() { - char - tmpstr[40]; + char tmpstr[40]; - sprintf (tmpstr, "Surprise! Adlib Tracker 2 (version %d)", header.version); - return std::string (tmpstr); + sprintf(tmpstr,"Surprise! Adlib Tracker 2 (version %d)",header.version); + return std::string(tmpstr); } -std::string Csa2Loader::gettitle () +std::string Csa2Loader::gettitle() { - char - bufinst[29 * 17], - buf[18]; - int - i, - ptr; + char bufinst[29*17],buf[18]; + int i,ptr; // parse instrument names for song name - memset (bufinst, '\0', 29 * 17); - for (i = 0; i < 29; i++) - { - buf[16] = ' '; - buf[17] = '\0'; - memcpy (buf, instname[i] + 1, 16); - for (ptr = 16; ptr > 0; ptr--) - if (buf[ptr] == ' ') + memset(bufinst,'\0',29*17); + for(i=0;i<29;i++) { + buf[16] = ' '; buf[17] = '\0'; + memcpy(buf,instname[i]+1,16); + for(ptr=16;ptr>0;ptr--) + if(buf[ptr] == ' ') buf[ptr] = '\0'; - else - { - if (ptr < 16) - buf[ptr + 1] = ' '; + else { + if(ptr<16) + buf[ptr+1] = ' '; break; } - strcat (bufinst, buf); + strcat(bufinst,buf); } - if (strchr (bufinst, '"')) - return std::string (bufinst, strchr (bufinst, '"') - bufinst + 1, - strrchr (bufinst, '"') - strchr (bufinst, '"') - 1); + if(strchr(bufinst,'"')) + return std::string(bufinst,strchr(bufinst,'"')-bufinst+1,strrchr(bufinst,'"')-strchr(bufinst,'"')-1); else - return std::string (); + return std::string(); } diff --git a/src/adplug/core/sa2.h b/src/adplug/core/sa2.h index 6176381..100782a 100644 --- a/src/adplug/core/sa2.h +++ b/src/adplug/core/sa2.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -27,29 +27,29 @@ class Csa2Loader: public CmodPlayer public: static CPlayer *factory(Copl *newopl); - Csa2Loader(Copl *newopl) - : CmodPlayer(newopl) - { } + Csa2Loader(Copl *newopl) + : CmodPlayer(newopl) + { } - bool load(VFSFile &fd, const CFileProvider &fp); + bool load(const std::string &filename, const CFileProvider &fp); - std::string gettype(); - std::string gettitle(); - unsigned int getinstruments() - { return 31; } - std::string getinstrument(unsigned int n) - { - if(n < 29) - return std::string(instname[n],1,16); - else - return std::string("-broken-"); - } + std::string gettype(); + std::string gettitle(); + unsigned int getinstruments() + { return 31; } + std::string getinstrument(unsigned int n) + { + if(n < 29) + return std::string(instname[n],1,16); + else + return std::string("-broken-"); + } private: - struct sa2header { - char sadt[4]; - unsigned char version; - } header; + struct sa2header { + char sadt[4]; + unsigned char version; + } header; - char instname[29][17]; + char instname[29][17]; }; diff --git a/src/adplug/core/silentopl.h b/src/adplug/core/silentopl.h index edfccf5..0df38d6 100644 --- a/src/adplug/core/silentopl.h +++ b/src/adplug/core/silentopl.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2005 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -24,6 +24,6 @@ class CSilentopl: public Copl { public: - void write(int reg, int val) {} - void init() {} + void write(int reg, int val) {} + void init() {} }; diff --git a/src/adplug/core/sng.cc b/src/adplug/core/sng.cc index 104c40c..89dbb3f 100644 --- a/src/adplug/core/sng.cc +++ b/src/adplug/core/sng.cc @@ -19,95 +19,67 @@ * sng.cpp - SNG Player by Simon Peter <dn.tlp@gmx.net> */ -#include <string.h> - +#include <cstring> #include "sng.h" -CPlayer * -CsngPlayer::factory (Copl * newopl) +CPlayer *CsngPlayer::factory(Copl *newopl) { - return new CsngPlayer (newopl); + return new CsngPlayer(newopl); } -bool -CsngPlayer::load (VFSFile & fd, const CFileProvider & fp) +bool CsngPlayer::load(const std::string &filename, const CFileProvider &fp) { - binistream *f = fp.open (fd); - if (!f) - return false; + binistream *f = fp.open(filename); if(!f) return false; int i; // load header - f->readString (header.id, 4); - header.length = f->readInt (2); - header.start = f->readInt (2); - header.loop = f->readInt (2); - header.delay = f->readInt (1); - header.compressed = f->readInt (1) ? true : false; + f->readString(header.id, 4); + header.length = f->readInt(2); header.start = f->readInt(2); + header.loop = f->readInt(2); header.delay = f->readInt(1); + header.compressed = f->readInt(1) ? true : false; // file validation section - if (strncmp (header.id, "ObsM", 4)) - { - fp.close (f); - return false; - } + if(strncmp(header.id,"ObsM",4)) { fp.close(f); return false; } // load section - header.length /= 2; - header.start /= 2; - header.loop /= 2; - data = new Sdata[header.length]; - for (i = 0; i < header.length; i++) - { - data[i].val = f->readInt (1); - data[i].reg = f->readInt (1); + header.length /= 2; header.start /= 2; header.loop /= 2; + data = new Sdata [header.length]; + for(i = 0; i < header.length; i++) { + data[i].val = f->readInt(1); + data[i].reg = f->readInt(1); } - rewind (0); - fp.close (f); + rewind(0); + fp.close(f); return true; } -bool -CsngPlayer::update () +bool CsngPlayer::update() { - if (header.compressed && del) - { + if(header.compressed && del) { del--; return !songend; } - while (data[pos].reg) - { - opl->write (data[pos].reg, data[pos].val); + while(data[pos].reg) { + opl->write(data[pos].reg, data[pos].val); pos++; - if (pos >= header.length) - { + if(pos >= header.length) { songend = true; pos = header.loop; } } - if (!header.compressed) - opl->write (data[pos].reg, data[pos].val); + if(!header.compressed) + opl->write(data[pos].reg, data[pos].val); - if (data[pos].val) - del = data[pos].val - 1; - pos++; - if (pos >= header.length) - { - songend = true; - pos = header.loop; - } + if(data[pos].val) del = data[pos].val - 1; pos++; + if(pos >= header.length) { songend = true; pos = header.loop; } return !songend; } -void -CsngPlayer::rewind (int subsong) +void CsngPlayer::rewind(int subsong) { - pos = header.start; - del = header.delay; - songend = false; - opl->init (); - opl->write (1, 32); // go to OPL2 mode + pos = header.start; del = header.delay; songend = false; + opl->init(); opl->write(1,32); // go to OPL2 mode } diff --git a/src/adplug/core/sng.h b/src/adplug/core/sng.h index 195a2f0..b7be3ba 100644 --- a/src/adplug/core/sng.h +++ b/src/adplug/core/sng.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2002 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -29,36 +29,36 @@ class CsngPlayer: public CPlayer public: static CPlayer *factory(Copl *newopl); - CsngPlayer(Copl *newopl) - : CPlayer(newopl), data(0) - { }; - - ~CsngPlayer() { if(data) delete [] data; data = 0; }; + CsngPlayer(Copl *newopl) + : CPlayer(newopl), data(0) + { }; + ~CsngPlayer() + { if(data) delete [] data; }; - bool load(VFSFile &fd, const CFileProvider &fp); - bool update(); - void rewind(int subsong); - float getrefresh() - { return 70.0f; }; + bool load(const std::string &filename, const CFileProvider &fp); + bool update(); + void rewind(int subsong); + float getrefresh() + { return 70.0f; }; - std::string gettype() - { return std::string("SNG File Format"); }; + std::string gettype() + { return std::string("SNG File Format"); }; protected: - struct { - char id[4]; - unsigned short length,start,loop; - unsigned char delay; - bool compressed; - } header; + struct { + char id[4]; + unsigned short length,start,loop; + unsigned char delay; + bool compressed; + } header; - struct Sdata { - unsigned char val,reg; - } *data; + struct Sdata { + unsigned char val,reg; + } *data; - unsigned char del; - unsigned short pos; - bool songend; + unsigned char del; + unsigned short pos; + bool songend; }; #endif diff --git a/src/adplug/core/temuopl.cc b/src/adplug/core/temuopl.cc index f0f5aab..930103e 100644 --- a/src/adplug/core/temuopl.cc +++ b/src/adplug/core/temuopl.cc @@ -1,17 +1,17 @@ /* * AdPlug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2004 Simon Peter <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -21,65 +21,55 @@ #include "temuopl.h" -CTemuopl::CTemuopl (int rate, bool bit16, bool usestereo): -use16bit (bit16), -stereo (usestereo) +CTemuopl::CTemuopl(int rate, bool bit16, bool usestereo) + : use16bit(bit16), stereo(usestereo) { - opl = OPLCreate (OPL_TYPE_YM3812, 3579545, rate); + opl = OPLCreate(OPL_TYPE_YM3812, 3579545, rate); } -CTemuopl::~CTemuopl () +CTemuopl::~CTemuopl() { - OPLDestroy (opl); + OPLDestroy(opl); } -void -CTemuopl::update (short *buf, int samples) +void CTemuopl::update(short *buf, int samples) { int i; - if (use16bit) - { - YM3812UpdateOne (opl, buf, samples); + if(use16bit) { + YM3812UpdateOne(opl,buf,samples); - if (stereo) - for (i = samples - 1; i >= 0; i--) - { - buf[i * 2] = buf[i]; - buf[i * 2 + 1] = buf[i]; + if(stereo) + for(i=samples-1;i>=0;i--) { + buf[i*2] = buf[i]; + buf[i*2+1] = buf[i]; } - } - else - { - short *tempbuf = new short[stereo ? samples * 2 : samples]; + } else { + short *tempbuf = new short[stereo ? samples*2 : samples]; int i; - YM3812UpdateOne (opl, tempbuf, samples); + YM3812UpdateOne(opl,tempbuf,samples); - if (stereo) - for (i = samples - 1; i >= 0; i--) - { - tempbuf[i * 2] = tempbuf[i]; - tempbuf[i * 2 + 1] = tempbuf[i]; + if(stereo) + for(i=samples-1;i>=0;i--) { + tempbuf[i*2] = tempbuf[i]; + tempbuf[i*2+1] = tempbuf[i]; } - for (i = 0; i < (stereo ? samples * 2 : samples); i++) - ((char *) buf)[i] = (tempbuf[i] >> 8) ^ 0x80; + for(i=0;i<(stereo ? samples*2 : samples);i++) + ((char *)buf)[i] = (tempbuf[i] >> 8) ^ 0x80; - delete[]tempbuf; - tempbuf = 0; + delete [] tempbuf; } } -void -CTemuopl::write (int reg, int val) +void CTemuopl::write(int reg, int val) { - OPLWrite (opl, 0, reg); - OPLWrite (opl, 1, val); + OPLWrite(opl,0,reg); + OPLWrite(opl,1,val); } -void -CTemuopl::init () +void CTemuopl::init() { - OPLResetChip (opl); + OPLResetChip(opl); } diff --git a/src/adplug/core/temuopl.h b/src/adplug/core/temuopl.h index 37908c0..b68b167 100644 --- a/src/adplug/core/temuopl.h +++ b/src/adplug/core/temuopl.h @@ -28,18 +28,18 @@ class CTemuopl: public Copl { public: - CTemuopl(int rate, bool bit16, bool usestereo); // rate = sample rate + CTemuopl(int rate, bool bit16, bool usestereo); // rate = sample rate virtual ~CTemuopl(); - void update(short *buf, int samples); // fill buffer + void update(short *buf, int samples); // fill buffer // template methods void write(int reg, int val); void init(); private: - bool use16bit,stereo; - FM_OPL *opl; // holds emulator data + bool use16bit,stereo; + FM_OPL *opl; // holds emulator data }; #endif diff --git a/src/adplug/core/u6m.cc b/src/adplug/core/u6m.cc index ce67a3a..d72ea09 100644 --- a/src/adplug/core/u6m.cc +++ b/src/adplug/core/u6m.cc @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2006 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -29,176 +29,166 @@ if(p < d.size) \ else \ return false; -CPlayer * -Cu6mPlayer::factory (Copl * newopl) +CPlayer *Cu6mPlayer::factory(Copl *newopl) { - return new Cu6mPlayer (newopl); + return new Cu6mPlayer(newopl); } -bool -Cu6mPlayer::load (VFSFile & fd, const CFileProvider & fp) +bool Cu6mPlayer::load(const std::string &filename, const CFileProvider &fp) { // file validation section // this section only checks a few *necessary* conditions unsigned long filesize, decompressed_filesize; binistream *f; - f = fp.open (fd); - if (!f) - return false; - filesize = fp.filesize (f); + f = fp.open(filename); if(!f) return false; + filesize = fp.filesize(f); if (filesize >= 6) - { - // check if the file has a valid pseudo-header - unsigned char pseudo_header[6]; - f->readString ((char *) pseudo_header, 6); - decompressed_filesize = pseudo_header[0] + (pseudo_header[1] << 8); - - if (!((pseudo_header[2] == 0) && (pseudo_header[3] == 0) && - (pseudo_header[4] + ((pseudo_header[5] & 0x1) << 8) == 0x100) && - (decompressed_filesize > (filesize - 4)))) { - fp.close (f); - return (false); + // check if the file has a valid pseudo-header + unsigned char pseudo_header[6]; + f->readString((char *)pseudo_header, 6); + decompressed_filesize = pseudo_header[0] + (pseudo_header[1] << 8); + + if (!( (pseudo_header[2]==0) && (pseudo_header[3]==0) && + (pseudo_header[4] + ((pseudo_header[5] & 0x1)<<8) == 0x100) && + (decompressed_filesize > (filesize-4)) )) + { + fp.close(f); + return(false); + } } - } else - { - fp.close (f); - return (false); - } + { + fp.close(f); + return(false); + } // load section song_data = new unsigned char[decompressed_filesize]; - unsigned char *compressed_song_data = new unsigned char[filesize - 3]; + unsigned char* compressed_song_data = new unsigned char[filesize-3]; - f->seek (4); - f->readString ((char *) compressed_song_data, filesize - 4); - fp.close (f); + f->seek(4); + f->readString((char *)compressed_song_data, filesize - 4); + fp.close(f); // attempt to decompress the song data // if unsuccessful, deallocate song_data[] on the spot, and return(false) data_block source, destination; - source.size = filesize - 4; + source.size = filesize-4; source.data = compressed_song_data; destination.size = decompressed_filesize; destination.data = song_data; - if (!lzw_decompress (source, destination)) - { - delete[]compressed_song_data; - compressed_song_data = 0; - delete[]song_data; - song_data = 0; - return (false); - } + if (!lzw_decompress(source,destination)) + { + delete[] compressed_song_data; + delete[] song_data; + return(false); + } // deallocation section - delete[]compressed_song_data; - compressed_song_data = 0; + delete[] compressed_song_data; - rewind (0); + rewind(0); return (true); } -bool -Cu6mPlayer::update () +bool Cu6mPlayer::update() { if (!driver_active) - { - driver_active = true; - dec_clip (read_delay); - if (read_delay == 0) - { - command_loop (); - } - - // on all Adlib channels: freq slide/vibrato, mute factor slide - for (int i = 0; i < 9; i++) { - if (channel_freq_signed_delta[i] != 0) - // frequency slide + mute factor slide - { - // freq slide - freq_slide (i); - - // mute factor slide - if (carrier_mf_signed_delta[i] != 0) + driver_active = true; + dec_clip(read_delay); + if (read_delay == 0) { - mf_slide (i); - } - } - else - // vibrato + mute factor slide - { - // vibrato - if ((vb_multiplier[i] != 0) && ((channel_freq[i].hi & 0x20) == 0x20)) - { - vibrato (i); + command_loop(); } - // mute factor slide - if (carrier_mf_signed_delta[i] != 0) + // on all Adlib channels: freq slide/vibrato, mute factor slide + for (int i = 0; i < 9; i++) { - mf_slide (i); + if (channel_freq_signed_delta[i]!=0) + // frequency slide + mute factor slide + { + // freq slide + freq_slide(i); + + // mute factor slide + if (carrier_mf_signed_delta[i]!=0) + { + mf_slide(i); + } + } + else + // vibrato + mute factor slide + { + // vibrato + if ((vb_multiplier[i]!=0) && ((channel_freq[i].hi & 0x20)==0x20)) + { + vibrato(i); + } + + // mute factor slide + if (carrier_mf_signed_delta[i]!=0) + { + mf_slide(i); + } + } } - } - } - driver_active = false; - } + driver_active = false; + } return !songend; } -void -Cu6mPlayer::rewind (int subsong) +void Cu6mPlayer::rewind(int subsong) { played_ticks = 0; songend = false; // set the driver's internal variables - byte_pair freq_word = { 0, 0 }; + byte_pair freq_word = {0,0}; driver_active = false; song_pos = 0; - loop_position = 0; // position of the loop point - read_delay = 0; // delay (in timer ticks) before further song data is read + loop_position = 0; // position of the loop point + read_delay = 0; // delay (in timer ticks) before further song data is read for (int i = 0; i < 9; i++) - { - // frequency - channel_freq_signed_delta[i] = 0; - channel_freq[i] = freq_word; // Adlib freq settings for each channel - - // vibrato ("vb") - vb_current_value[i] = 0; - vb_double_amplitude[i] = 0; - vb_multiplier[i] = 0; - vb_direction_flag[i] = 0; - - // mute factor ("mf") == ~(volume) - carrier_mf[i] = 0; - carrier_mf_signed_delta[i] = 0; - carrier_mf_mod_delay_backup[i] = 0; - carrier_mf_mod_delay[i] = 0; - } - - while (!subsong_stack.empty ()) // empty subsong stack - subsong_stack.pop (); - - opl->init (); - out_adlib (1, 32); // go to OPL2 mode + { + // frequency + channel_freq_signed_delta[i] = 0; + channel_freq[i] = freq_word; // Adlib freq settings for each channel + + // vibrato ("vb") + vb_current_value[i] = 0; + vb_double_amplitude[i] = 0; + vb_multiplier[i] = 0; + vb_direction_flag[i] = 0; + + // mute factor ("mf") == ~(volume) + carrier_mf[i] = 0; + carrier_mf_signed_delta[i] = 0; + carrier_mf_mod_delay_backup[i] = 0; + carrier_mf_mod_delay[i] = 0; + } + + while (!subsong_stack.empty()) // empty subsong stack + subsong_stack.pop(); + + opl->init(); + out_adlib(1,32); // go to OPL2 mode } -float -Cu6mPlayer::getrefresh () +float Cu6mPlayer::getrefresh() { - return ((float) 60); // the Ultima 6 music driver expects to be called at 60 Hz + return ((float)60); // the Ultima 6 music driver expects to be called at 60 Hz } @@ -212,109 +202,108 @@ Cu6mPlayer::getrefresh () // decompress from memory to memory -bool -Cu6mPlayer::lzw_decompress (Cu6mPlayer::data_block source, - Cu6mPlayer::data_block dest) +bool Cu6mPlayer::lzw_decompress(Cu6mPlayer::data_block source, Cu6mPlayer::data_block dest) { bool end_marker_reached = false; int codeword_size = 9; long bits_read = 0; int next_free_codeword = 0x102; int dictionary_size = 0x200; - MyDict dictionary = MyDict (); - std::stack < unsigned char >root_stack; + MyDict dictionary = MyDict(); + std::stack<unsigned char> root_stack; long bytes_written = 0; - int cW, pW = 0; + int cW; + int pW = 0; unsigned char C; while (!end_marker_reached) - { - cW = get_next_codeword (bits_read, source.data, codeword_size); - switch (cW) { - // re-init the dictionary - case 0x100: - codeword_size = 9; - next_free_codeword = 0x102; - dictionary_size = 0x200; - dictionary.reset (); - cW = get_next_codeword (bits_read, source.data, codeword_size); - SAVE_OUTPUT_ROOT ((unsigned char) cW, dest, bytes_written); - break; - // end of compressed file has been reached - case 0x101: - end_marker_reached = true; - break; - // (cW <> 0x100) && (cW <> 0x101) - default: - if (cW < next_free_codeword) // codeword is already in the dictionary - { - // create the string associated with cW (on the stack) - get_string (cW, dictionary, root_stack); - C = root_stack.top (); - // output the string represented by cW - while (!root_stack.empty ()) - { - SAVE_OUTPUT_ROOT (root_stack.top (), dest, bytes_written); - root_stack.pop (); - } - // add pW+C to the dictionary - dictionary.add (C, pW); - - next_free_codeword++; - if (next_free_codeword >= dictionary_size) - { - if (codeword_size < max_codeword_length) - { - codeword_size += 1; - dictionary_size *= 2; - } - } - } - else // codeword is not yet defined - { - // create the string associated with pW (on the stack) - get_string (pW, dictionary, root_stack); - C = root_stack.top (); - // output the string represented by pW - while (!root_stack.empty ()) - { - SAVE_OUTPUT_ROOT (root_stack.top (), dest, bytes_written); - root_stack.pop (); - } - // output the char C - SAVE_OUTPUT_ROOT (C, dest, bytes_written); - - // the new dictionary entry must correspond to cW - // if it doesn't, something is wrong with the lzw-compressed data. - if (cW != next_free_codeword) - { - /* printf("cW != next_free_codeword!\n"); - exit(-1); */ - return false; - } - // add pW+C to the dictionary - dictionary.add (C, pW); - - next_free_codeword++; - if (next_free_codeword >= dictionary_size) + cW = get_next_codeword(bits_read, source.data, codeword_size); + switch (cW) { - if (codeword_size < max_codeword_length) - { - codeword_size += 1; - dictionary_size *= 2; - } + // re-init the dictionary + case 0x100: + codeword_size = 9; + next_free_codeword = 0x102; + dictionary_size = 0x200; + dictionary.reset(); + cW = get_next_codeword(bits_read, source.data, codeword_size); + SAVE_OUTPUT_ROOT((unsigned char)cW, dest, bytes_written); + break; + // end of compressed file has been reached + case 0x101: + end_marker_reached = true; + break; + // (cW <> 0x100) && (cW <> 0x101) + default: + if (cW < next_free_codeword) // codeword is already in the dictionary + { + // create the string associated with cW (on the stack) + get_string(cW,dictionary,root_stack); + C = root_stack.top(); + // output the string represented by cW + while (!root_stack.empty()) + { + SAVE_OUTPUT_ROOT(root_stack.top(), dest, bytes_written); + root_stack.pop(); + } + // add pW+C to the dictionary + dictionary.add(C,pW); + + next_free_codeword++; + if (next_free_codeword >= dictionary_size) + { + if (codeword_size < max_codeword_length) + { + codeword_size += 1; + dictionary_size *= 2; + } + } + } + else // codeword is not yet defined + { + // create the string associated with pW (on the stack) + get_string(pW,dictionary,root_stack); + C = root_stack.top(); + // output the string represented by pW + while (!root_stack.empty()) + { + SAVE_OUTPUT_ROOT(root_stack.top(), dest, bytes_written); + root_stack.pop(); + } + // output the char C + SAVE_OUTPUT_ROOT(C, dest, bytes_written); + + // the new dictionary entry must correspond to cW + // if it doesn't, something is wrong with the lzw-compressed data. + if (cW != next_free_codeword) + { + /* printf("cW != next_free_codeword!\n"); + exit(-1); */ + return false; + } + // add pW+C to the dictionary + dictionary.add(C,pW); + + next_free_codeword++; + if (next_free_codeword >= dictionary_size) + { + if (codeword_size < max_codeword_length) + { + codeword_size += 1; + dictionary_size *= 2; + } + } + }; + break; } - }; - break; + // shift roles - the current cW becomes the new pW + pW = cW; } - // shift roles - the current cW becomes the new pW - pW = cW; - } - return (true); // indicate successful decompression + return(true); // indicate successful decompression } @@ -324,37 +313,35 @@ Cu6mPlayer::lzw_decompress (Cu6mPlayer::data_block source, // Read the next code word from the source buffer -int -Cu6mPlayer::get_next_codeword (long &bits_read, unsigned char *source, - int codeword_size) +int Cu6mPlayer::get_next_codeword (long& bits_read, unsigned char *source, int codeword_size) { - unsigned char b0, b1, b2; + unsigned char b0,b1,b2; int codeword; - b0 = source[bits_read / 8]; - b1 = source[bits_read / 8 + 1]; - b2 = source[bits_read / 8 + 2]; + b0 = source[bits_read/8]; + b1 = source[bits_read/8+1]; + b2 = source[bits_read/8+2]; codeword = ((b2 << 16) + (b1 << 8) + b0); codeword = codeword >> (bits_read % 8); switch (codeword_size) - { - case 0x9: - codeword = codeword & 0x1ff; - break; - case 0xa: - codeword = codeword & 0x3ff; - break; - case 0xb: - codeword = codeword & 0x7ff; - break; - case 0xc: - codeword = codeword & 0xfff; - break; - default: - codeword = -1; // indicates that an error has occurred - break; - } + { + case 0x9: + codeword = codeword & 0x1ff; + break; + case 0xa: + codeword = codeword & 0x3ff; + break; + case 0xb: + codeword = codeword & 0x7ff; + break; + case 0xc: + codeword = codeword & 0xfff; + break; + default: + codeword = -1; // indicates that an error has occurred + break; + } bits_read += codeword_size; return (codeword); @@ -362,9 +349,7 @@ Cu6mPlayer::get_next_codeword (long &bits_read, unsigned char *source, // output a root to memory -void -Cu6mPlayer::output_root (unsigned char root, unsigned char *destination, - long &position) +void Cu6mPlayer::output_root(unsigned char root, unsigned char *destination, long& position) { destination[position] = root; position++; @@ -372,9 +357,7 @@ Cu6mPlayer::output_root (unsigned char root, unsigned char *destination, // output the string represented by a codeword -void -Cu6mPlayer::get_string (int codeword, Cu6mPlayer::MyDict & dictionary, - std::stack < unsigned char >&root_stack) +void Cu6mPlayer::get_string(int codeword, Cu6mPlayer::MyDict& dictionary, std::stack<unsigned char>& root_stack) { unsigned char root; int current_codeword; @@ -382,14 +365,14 @@ Cu6mPlayer::get_string (int codeword, Cu6mPlayer::MyDict & dictionary, current_codeword = codeword; while (current_codeword > 0xff) - { - root = dictionary.get_root (current_codeword); - current_codeword = dictionary.get_codeword (current_codeword); - root_stack.push (root); - } + { + root = dictionary.get_root(current_codeword); + current_codeword = dictionary.get_codeword(current_codeword); + root_stack.push(root); + } // push the root at the leaf - root_stack.push ((unsigned char) current_codeword); + root_stack.push((unsigned char)current_codeword); } @@ -403,8 +386,7 @@ Cu6mPlayer::get_string (int codeword, Cu6mPlayer::MyDict & dictionary, // This function reads the song data and executes the embedded commands. -void -Cu6mPlayer::command_loop () +void Cu6mPlayer::command_loop() { unsigned char command_byte; // current command byte int command_nibble_hi; // command byte, bits 4-7 @@ -412,72 +394,39 @@ Cu6mPlayer::command_loop () bool repeat_loop = true; // do - { - // extract low and high command nibbles - command_byte = read_song_byte (); // implicitly increments song_pos - command_nibble_hi = command_byte >> 4; - command_nibble_lo = command_byte & 0xf; - - switch (command_nibble_hi) { - case 0x0: - command_0 (command_nibble_lo); - break; - case 0x1: - command_1 (command_nibble_lo); - break; - case 0x2: - command_2 (command_nibble_lo); - break; - case 0x3: - command_3 (command_nibble_lo); - break; - case 0x4: - command_4 (command_nibble_lo); - break; - case 0x5: - command_5 (command_nibble_lo); - break; - case 0x6: - command_6 (command_nibble_lo); - break; - case 0x7: - command_7 (command_nibble_lo); - break; - case 0x8: - switch (command_nibble_lo) - { - case 1: - command_81 (); - break; - case 2: - command_82 (); - repeat_loop = false; - break; - case 3: - command_83 (); - break; - case 5: - command_85 (); - break; - case 6: - command_86 (); - break; - default: - break; // maybe generate an error? - } - break; - case 0xE: - command_E (); - break; - case 0xF: - command_F (); - break; - default: - break; // maybe generate an error? - } + // extract low and high command nibbles + command_byte = read_song_byte(); // implicitly increments song_pos + command_nibble_hi = command_byte >> 4; + command_nibble_lo = command_byte & 0xf; + + switch (command_nibble_hi) + { + case 0x0: command_0(command_nibble_lo); break; + case 0x1: command_1(command_nibble_lo); break; + case 0x2: command_2(command_nibble_lo); break; + case 0x3: command_3(command_nibble_lo); break; + case 0x4: command_4(command_nibble_lo); break; + case 0x5: command_5(command_nibble_lo); break; + case 0x6: command_6(command_nibble_lo); break; + case 0x7: command_7(command_nibble_lo); break; + case 0x8: + switch (command_nibble_lo) + { + case 1: command_81(); break; + case 2: command_82(); repeat_loop = false; break; + case 3: command_83(); break; + case 5: command_85(); break; + case 6: command_86(); break; + default: break; // maybe generate an error? + } + break; + case 0xE: command_E(); break; + case 0xF: command_F(); break; + default: break; // maybe generate an error? + } - } while (repeat_loop); + } while (repeat_loop); } @@ -490,15 +439,14 @@ Cu6mPlayer::command_loop () // Format: 0c nn // c = channel, nn = packed Adlib frequency // ---------------------------------------- -void -Cu6mPlayer::command_0 (int channel) +void Cu6mPlayer::command_0(int channel) { unsigned char freq_byte; byte_pair freq_word; - freq_byte = read_song_byte (); - freq_word = expand_freq_byte (freq_byte); - set_adlib_freq (channel, freq_word); + freq_byte = read_song_byte(); + freq_word = expand_freq_byte(freq_byte); + set_adlib_freq(channel,freq_word); } @@ -507,8 +455,7 @@ Cu6mPlayer::command_0 (int channel) // Format: 1c nn // c = channel, nn = packed Adlib frequency // --------------------------------------------------- -void -Cu6mPlayer::command_1 (int channel) +void Cu6mPlayer::command_1(int channel) { unsigned char freq_byte; byte_pair freq_word; @@ -516,12 +463,12 @@ Cu6mPlayer::command_1 (int channel) vb_direction_flag[channel] = 0; vb_current_value[channel] = 0; - freq_byte = read_song_byte (); - freq_word = expand_freq_byte (freq_byte); - set_adlib_freq (channel, freq_word); + freq_byte = read_song_byte(); + freq_word = expand_freq_byte(freq_byte); + set_adlib_freq(channel,freq_word); - freq_word.hi = freq_word.hi | 0x20; // note on - set_adlib_freq (channel, freq_word); + freq_word.hi = freq_word.hi | 0x20; // note on + set_adlib_freq(channel,freq_word); } @@ -530,16 +477,15 @@ Cu6mPlayer::command_1 (int channel) // Format: 2c nn // c = channel, nn = packed Adlib frequency // ---------------------------------------- -void -Cu6mPlayer::command_2 (int channel) +void Cu6mPlayer::command_2(int channel) { unsigned char freq_byte; byte_pair freq_word; - freq_byte = read_song_byte (); - freq_word = expand_freq_byte (freq_byte); - freq_word.hi = freq_word.hi | 0x20; // note on - set_adlib_freq (channel, freq_word); + freq_byte = read_song_byte(); + freq_word = expand_freq_byte(freq_byte); + freq_word.hi = freq_word.hi | 0x20; // note on + set_adlib_freq(channel,freq_word); } @@ -548,14 +494,13 @@ Cu6mPlayer::command_2 (int channel) // Format: 3c nn // c = channel, nn = mute factor // -------------------------------------- -void -Cu6mPlayer::command_3 (int channel) +void Cu6mPlayer::command_3(int channel) { unsigned char mf_byte; carrier_mf_signed_delta[channel] = 0; - mf_byte = read_song_byte (); - set_carrier_mf (channel, mf_byte); + mf_byte = read_song_byte(); + set_carrier_mf(channel,mf_byte); } @@ -564,13 +509,12 @@ Cu6mPlayer::command_3 (int channel) // Format: 4c nn // c = channel, nn = mute factor // ---------------------------------------- -void -Cu6mPlayer::command_4 (int channel) +void Cu6mPlayer::command_4(int channel) { unsigned char mf_byte; - mf_byte = read_song_byte (); - set_modulator_mf (channel, mf_byte); + mf_byte = read_song_byte(); + set_modulator_mf(channel,mf_byte); } @@ -579,10 +523,9 @@ Cu6mPlayer::command_4 (int channel) // Format: 5c nn // c = channel, nn = signed channel pitch delta // -------------------------------------------- -void -Cu6mPlayer::command_5 (int channel) +void Cu6mPlayer::command_5(int channel) { - channel_freq_signed_delta[channel] = read_signed_song_byte (); + channel_freq_signed_delta[channel] = read_signed_song_byte(); } @@ -593,13 +536,12 @@ Cu6mPlayer::command_5 (int channel) // m = vibrato double amplitude // n = vibrato multiplier // -------------------------------------------- -void -Cu6mPlayer::command_6 (int channel) +void Cu6mPlayer::command_6(int channel) { unsigned char vb_parameters; - vb_parameters = read_song_byte (); - vb_double_amplitude[channel] = vb_parameters >> 4; // high nibble + vb_parameters = read_song_byte(); + vb_double_amplitude[channel] = vb_parameters >> 4; // high nibble vb_multiplier[channel] = vb_parameters & 0xF; // low nibble } @@ -609,31 +551,20 @@ Cu6mPlayer::command_6 (int channel) // Format: 7c nn // c = channel, nn = instrument number // ---------------------------------------- -void -Cu6mPlayer::command_7 (int channel) +void Cu6mPlayer::command_7(int channel) { - int instrument_offset = instrument_offsets[read_song_byte ()]; - out_adlib_opcell (channel, false, 0x20, - *(song_data + instrument_offset + 0)); - out_adlib_opcell (channel, false, 0x40, - *(song_data + instrument_offset + 1)); - out_adlib_opcell (channel, false, 0x60, - *(song_data + instrument_offset + 2)); - out_adlib_opcell (channel, false, 0x80, - *(song_data + instrument_offset + 3)); - out_adlib_opcell (channel, false, 0xE0, - *(song_data + instrument_offset + 4)); - out_adlib_opcell (channel, true, 0x20, - *(song_data + instrument_offset + 5)); - out_adlib_opcell (channel, true, 0x40, - *(song_data + instrument_offset + 6)); - out_adlib_opcell (channel, true, 0x60, - *(song_data + instrument_offset + 7)); - out_adlib_opcell (channel, true, 0x80, - *(song_data + instrument_offset + 8)); - out_adlib_opcell (channel, true, 0xE0, - *(song_data + instrument_offset + 9)); - out_adlib (0xC0 + channel, *(song_data + instrument_offset + 10)); + int instrument_offset = instrument_offsets[read_song_byte()]; + out_adlib_opcell(channel, false, 0x20, *(song_data + instrument_offset+0)); + out_adlib_opcell(channel, false, 0x40, *(song_data + instrument_offset+1)); + out_adlib_opcell(channel, false, 0x60, *(song_data + instrument_offset+2)); + out_adlib_opcell(channel, false, 0x80, *(song_data + instrument_offset+3)); + out_adlib_opcell(channel, false, 0xE0, *(song_data + instrument_offset+4)); + out_adlib_opcell(channel, true, 0x20, *(song_data + instrument_offset+5)); + out_adlib_opcell(channel, true, 0x40, *(song_data + instrument_offset+6)); + out_adlib_opcell(channel, true, 0x60, *(song_data + instrument_offset+7)); + out_adlib_opcell(channel, true, 0x80, *(song_data + instrument_offset+8)); + out_adlib_opcell(channel, true, 0xE0, *(song_data + instrument_offset+9)); + out_adlib(0xC0+channel, *(song_data + instrument_offset+10)); } @@ -644,17 +575,15 @@ Cu6mPlayer::command_7 (int channel) // aa == subsong offset (low byte) // bb == subsong offset (high byte) // ------------------------------------------- -void -Cu6mPlayer::command_81 () +void Cu6mPlayer::command_81() { subsong_info new_ss_info; - new_ss_info.subsong_repetitions = read_song_byte (); - new_ss_info.subsong_start = read_song_byte (); - new_ss_info.subsong_start += read_song_byte () << 8; + new_ss_info.subsong_repetitions = read_song_byte(); + new_ss_info.subsong_start = read_song_byte(); new_ss_info.subsong_start += read_song_byte() << 8; new_ss_info.continue_pos = song_pos; - subsong_stack.push (new_ss_info); + subsong_stack.push(new_ss_info); song_pos = new_ss_info.subsong_start; } @@ -664,10 +593,9 @@ Cu6mPlayer::command_81 () // Format: 82 nn // nn == delay (in timer ticks) until further data will be read // ------------------------------------------------------------ -void -Cu6mPlayer::command_82 () +void Cu6mPlayer::command_82() { - read_delay = read_song_byte (); + read_delay = read_song_byte(); } @@ -676,10 +604,9 @@ Cu6mPlayer::command_82 () // Format: 83 nn <11 bytes> // nn == instrument number // ----------------------------- -void -Cu6mPlayer::command_83 () +void Cu6mPlayer::command_83() { - unsigned char instrument_number = read_song_byte (); + unsigned char instrument_number = read_song_byte(); instrument_offsets[instrument_number] = song_pos; song_pos += 11; } @@ -691,12 +618,11 @@ Cu6mPlayer::command_83 () // c == channel // n == slide delay // ---------------------------------------------- -void -Cu6mPlayer::command_85 () +void Cu6mPlayer::command_85() { - unsigned char data_byte = read_song_byte (); + unsigned char data_byte = read_song_byte(); int channel = data_byte >> 4; // high nibble - unsigned char slide_delay = data_byte & 0xF; // low nibble + unsigned char slide_delay = data_byte & 0xF; // low nibble carrier_mf_signed_delta[channel] = +1; carrier_mf_mod_delay[channel] = slide_delay + 1; carrier_mf_mod_delay_backup[channel] = slide_delay + 1; @@ -709,12 +635,11 @@ Cu6mPlayer::command_85 () // c == channel // n == slide speed // ------------------------------------------------ -void -Cu6mPlayer::command_86 () +void Cu6mPlayer::command_86() { - unsigned char data_byte = read_song_byte (); + unsigned char data_byte = read_song_byte(); int channel = data_byte >> 4; // high nibble - unsigned char slide_delay = data_byte & 0xF; // low nibble + unsigned char slide_delay = data_byte & 0xF; // low nibble carrier_mf_signed_delta[channel] = -1; carrier_mf_mod_delay[channel] = slide_delay + 1; carrier_mf_mod_delay_backup[channel] = slide_delay + 1; @@ -725,8 +650,7 @@ Cu6mPlayer::command_86 () // Set loop point // Format: E? // -------------- -void -Cu6mPlayer::command_E () +void Cu6mPlayer::command_E() { loop_position = song_pos; } @@ -736,29 +660,28 @@ Cu6mPlayer::command_E () // Return from current subsong // Format: F? // --------------------------- -void -Cu6mPlayer::command_F () +void Cu6mPlayer::command_F() { - if (!subsong_stack.empty ()) - { - subsong_info temp = subsong_stack.top (); - subsong_stack.pop (); - temp.subsong_repetitions--; - if (temp.subsong_repetitions == 0) + if (!subsong_stack.empty()) { - song_pos = temp.continue_pos; + subsong_info temp = subsong_stack.top(); + subsong_stack.pop(); + temp.subsong_repetitions--; + if (temp.subsong_repetitions==0) + { + song_pos = temp.continue_pos; + } + else + { + song_pos = temp.subsong_start; + subsong_stack.push(temp); + } } - else + else { - song_pos = temp.subsong_start; - subsong_stack.push (temp); + song_pos = loop_position; + songend = true; } - } - else - { - song_pos = loop_position; - songend = true; - } } @@ -767,234 +690,186 @@ Cu6mPlayer::command_F () // -------------------- // This function decrements its argument, without allowing it to become negative. -void -Cu6mPlayer::dec_clip (int ¶m) +void Cu6mPlayer::dec_clip(int& param) { param--; - if (param < 0) - { - param = 0; - } + if (param < 0) { param = 0; } } // Returns the byte at the current song position. // Side effect: increments song_pos. -unsigned char -Cu6mPlayer::read_song_byte () +unsigned char Cu6mPlayer::read_song_byte() { unsigned char song_byte; song_byte = song_data[song_pos]; song_pos++; - return (song_byte); + return(song_byte); } // Same as read_song_byte(), except that it returns a signed byte -signed char -Cu6mPlayer::read_signed_song_byte () +signed char Cu6mPlayer::read_signed_song_byte() { unsigned char song_byte; int signed_value; song_byte = *(song_data + song_pos); song_pos++; if (song_byte <= 127) - { - signed_value = song_byte; - } + { + signed_value = song_byte; + } else - { - signed_value = (int) song_byte - 0x100; - } - return ((signed char) signed_value); + { + signed_value = (int)song_byte - 0x100; + } + return((signed char)signed_value); } -Cu6mPlayer::byte_pair Cu6mPlayer::expand_freq_byte (unsigned char freq_byte) +Cu6mPlayer::byte_pair Cu6mPlayer::expand_freq_byte(unsigned char freq_byte) { - const byte_pair - freq_table[24] = { - {0x00, 0x00}, {0x58, 0x01}, {0x82, 0x01}, {0xB0, 0x01}, - {0xCC, 0x01}, {0x03, 0x02}, {0x41, 0x02}, {0x86, 0x02}, - {0x00, 0x00}, {0x6A, 0x01}, {0x96, 0x01}, {0xC7, 0x01}, - {0xE4, 0x01}, {0x1E, 0x02}, {0x5F, 0x02}, {0xA8, 0x02}, - {0x00, 0x00}, {0x47, 0x01}, {0x6E, 0x01}, {0x9A, 0x01}, - {0xB5, 0x01}, {0xE9, 0x01}, {0x24, 0x02}, {0x66, 0x02} - }; - - int - packed_freq; - int - octave; - byte_pair - freq_word; + const byte_pair freq_table[24] = + { + {0x00,0x00}, {0x58,0x01}, {0x82,0x01}, {0xB0,0x01}, + {0xCC,0x01}, {0x03,0x02}, {0x41,0x02}, {0x86,0x02}, + {0x00,0x00}, {0x6A,0x01}, {0x96,0x01}, {0xC7,0x01}, + {0xE4,0x01}, {0x1E,0x02}, {0x5F,0x02}, {0xA8,0x02}, + {0x00,0x00}, {0x47,0x01}, {0x6E,0x01}, {0x9A,0x01}, + {0xB5,0x01}, {0xE9,0x01}, {0x24,0x02}, {0x66,0x02} + }; + + int packed_freq; + int octave; + byte_pair freq_word; packed_freq = freq_byte & 0x1F; octave = freq_byte >> 5; // range check (not present in the original U6 music driver) - if (packed_freq >= 24) - { - packed_freq = 0; - } + if (packed_freq >= 24) { packed_freq = 0; } freq_word.hi = freq_table[packed_freq].hi + (octave << 2); freq_word.lo = freq_table[packed_freq].lo; - return (freq_word); + return(freq_word); } -void -Cu6mPlayer::set_adlib_freq (int channel, Cu6mPlayer::byte_pair freq_word) +void Cu6mPlayer::set_adlib_freq(int channel,Cu6mPlayer::byte_pair freq_word) { - out_adlib (0xA0 + channel, freq_word.lo); - out_adlib (0xB0 + channel, freq_word.hi); + out_adlib(0xA0+channel,freq_word.lo); + out_adlib(0xB0+channel,freq_word.hi); // update the Adlib register backups channel_freq[channel] = freq_word; } // this function sets the Adlib frequency, but does not update the register backups -void -Cu6mPlayer::set_adlib_freq_no_update (int channel, - Cu6mPlayer::byte_pair freq_word) +void Cu6mPlayer::set_adlib_freq_no_update(int channel,Cu6mPlayer::byte_pair freq_word) { - out_adlib (0xA0 + channel, freq_word.lo); - out_adlib (0xB0 + channel, freq_word.hi); + out_adlib(0xA0+channel,freq_word.lo); + out_adlib(0xB0+channel,freq_word.hi); } -void -Cu6mPlayer::set_carrier_mf (int channel, unsigned char mute_factor) +void Cu6mPlayer::set_carrier_mf(int channel,unsigned char mute_factor) { - out_adlib_opcell (channel, true, 0x40, mute_factor); + out_adlib_opcell(channel,true,0x40,mute_factor); carrier_mf[channel] = mute_factor; } -void -Cu6mPlayer::set_modulator_mf (int channel, unsigned char mute_factor) +void Cu6mPlayer::set_modulator_mf(int channel,unsigned char mute_factor) { - out_adlib_opcell (channel, false, 0x40, mute_factor); + out_adlib_opcell(channel,false,0x40,mute_factor); } -void -Cu6mPlayer::freq_slide (int channel) +void Cu6mPlayer::freq_slide(int channel) { byte_pair freq = channel_freq[channel]; - long freq_word = - freq.lo + (freq.hi << 8) + channel_freq_signed_delta[channel]; - if (freq_word < 0) - { - freq_word += 0x10000; - } - if (freq_word > 0xFFFF) - { - freq_word -= 0x10000; - } + long freq_word = freq.lo + (freq.hi << 8) + channel_freq_signed_delta[channel]; + if (freq_word < 0) { freq_word += 0x10000; } + if (freq_word > 0xFFFF) { freq_word -= 0x10000; } freq.lo = freq_word & 0xFF; freq.hi = (freq_word >> 8) & 0xFF; - set_adlib_freq (channel, freq); + set_adlib_freq(channel,freq); } -void -Cu6mPlayer::vibrato (int channel) +void Cu6mPlayer::vibrato(int channel) { byte_pair freq; if (vb_current_value[channel] >= vb_double_amplitude[channel]) - { - vb_direction_flag[channel] = 1; - } + { vb_direction_flag[channel] = 1; } else if (vb_current_value[channel] <= 0) - { - vb_direction_flag[channel] = 0; - } - - if (vb_direction_flag[channel] == 0) - { - vb_current_value[channel]++; - } + { vb_direction_flag[channel] = 0; } + + if (vb_direction_flag[channel]==0) + { vb_current_value[channel]++; } else - { - vb_current_value[channel]--; - } + { vb_current_value[channel]--; } long freq_word = channel_freq[channel].lo + (channel_freq[channel].hi << 8); - freq_word += - (vb_current_value[channel] - - (vb_double_amplitude[channel] >> 1)) * vb_multiplier[channel]; - if (freq_word < 0) - { - freq_word += 0x10000; - } - if (freq_word > 0xFFFF) - { - freq_word -= 0x10000; - } + freq_word += (vb_current_value[channel] - (vb_double_amplitude[channel] >> 1)) + * vb_multiplier[channel]; + if (freq_word < 0) { freq_word += 0x10000; } + if (freq_word > 0xFFFF) { freq_word -= 0x10000; } freq.lo = freq_word & 0xFF; freq.hi = (freq_word >> 8) & 0xFF; - set_adlib_freq_no_update (channel, freq); + set_adlib_freq_no_update(channel,freq); } -void -Cu6mPlayer::mf_slide (int channel) +void Cu6mPlayer::mf_slide(int channel) { carrier_mf_mod_delay[channel]--; - if (carrier_mf_mod_delay[channel] == 0) - { - carrier_mf_mod_delay[channel] = carrier_mf_mod_delay_backup[channel]; - int current_mf = carrier_mf[channel] + carrier_mf_signed_delta[channel]; - if (current_mf > 0x3F) + if (carrier_mf_mod_delay[channel]==0) { - current_mf = 0x3F; - carrier_mf_signed_delta[channel] = 0; - } - else if (current_mf < 0) - { - current_mf = 0; - carrier_mf_signed_delta[channel] = 0; - } + carrier_mf_mod_delay[channel] = carrier_mf_mod_delay_backup[channel]; + int current_mf = carrier_mf[channel] + carrier_mf_signed_delta[channel]; + if (current_mf > 0x3F) + { + current_mf = 0x3F; + carrier_mf_signed_delta[channel] = 0; + } + else if (current_mf < 0) + { + current_mf = 0; + carrier_mf_signed_delta[channel] = 0; + } - set_carrier_mf (channel, (unsigned char) current_mf); - } + set_carrier_mf(channel,(unsigned char)current_mf); + } } -void -Cu6mPlayer::out_adlib (unsigned char adlib_register, unsigned char adlib_data) +void Cu6mPlayer::out_adlib(unsigned char adlib_register, unsigned char adlib_data) { - opl->write (adlib_register, adlib_data); + opl->write(adlib_register,adlib_data); } -void -Cu6mPlayer::out_adlib_opcell (int channel, bool carrier, - unsigned char adlib_register, - unsigned char out_byte) +void Cu6mPlayer::out_adlib_opcell(int channel, bool carrier, unsigned char adlib_register, unsigned char out_byte) { const unsigned char adlib_channel_to_carrier_offset[9] = - { 0x03, 0x04, 0x05, 0x0B, 0x0C, 0x0D, 0x13, 0x14, 0x15 }; + {0x03,0x04,0x05,0x0B,0x0C,0x0D,0x13,0x14,0x15}; const unsigned char adlib_channel_to_modulator_offset[9] = - { 0x00, 0x01, 0x02, 0x08, 0x09, 0x0A, 0x10, 0x11, 0x12 }; + {0x00,0x01,0x02,0x08,0x09,0x0A,0x10,0x11,0x12}; if (carrier) - { - out_adlib (adlib_register + adlib_channel_to_carrier_offset[channel], - out_byte); - } + { + out_adlib(adlib_register+adlib_channel_to_carrier_offset[channel],out_byte); + } else - { - out_adlib (adlib_register + adlib_channel_to_modulator_offset[channel], - out_byte); - } + { + out_adlib(adlib_register+adlib_channel_to_modulator_offset[channel],out_byte); + } } @@ -1007,58 +882,53 @@ Cu6mPlayer::out_adlib_opcell (int channel, bool carrier, // ============================================================================================ -Cu6mPlayer::MyDict::MyDict () +Cu6mPlayer::MyDict::MyDict() { dict_size = default_dict_size; - dictionary = new dict_entry[dict_size - 0x100]; // don't allocate space for the roots + dictionary = new dict_entry[dict_size-0x100]; // don't allocate space for the roots contains = 0x102; } -Cu6mPlayer::MyDict::MyDict (int max_size) +Cu6mPlayer::MyDict::MyDict(int max_size) { dict_size = max_size; - dictionary = new dict_entry[dict_size - 0x100]; // don't allocate space for the roots + dictionary = new dict_entry[dict_size-0x100]; // don't allocate space for the roots contains = 0x102; } -Cu6mPlayer::MyDict::~MyDict () +Cu6mPlayer::MyDict::~MyDict() { - delete[]dictionary; - dictionary = 0; + delete [] dictionary; } // re-initializes the dictionary -void -Cu6mPlayer::MyDict::reset () +void Cu6mPlayer::MyDict::reset() { contains = 0x102; } // Note: If the dictionary is already full, this function does nothing. -void -Cu6mPlayer::MyDict::add (unsigned char root, int codeword) +void Cu6mPlayer::MyDict::add(unsigned char root, int codeword) { if (contains < dict_size) - { - dictionary[contains - 0x100].root = root; - dictionary[contains - 0x100].codeword = codeword; - contains++; - } + { + dictionary[contains-0x100].root = root; + dictionary[contains-0x100].codeword = codeword; + contains++; + } } -unsigned char -Cu6mPlayer::MyDict::get_root (int codeword) +unsigned char Cu6mPlayer::MyDict::get_root(int codeword) { - return (dictionary[codeword - 0x100].root); + return (dictionary[codeword-0x100].root); } -int -Cu6mPlayer::MyDict::get_codeword (int codeword) +int Cu6mPlayer::MyDict::get_codeword(int codeword) { - return (dictionary[codeword - 0x100].codeword); + return (dictionary[codeword-0x100].codeword); } diff --git a/src/adplug/core/u6m.h b/src/adplug/core/u6m.h index 302047b..cd593e5 100644 --- a/src/adplug/core/u6m.h +++ b/src/adplug/core/u6m.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2006 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -29,139 +29,140 @@ class Cu6mPlayer: public CPlayer { - public: + public: static CPlayer *factory(Copl *newopl); - Cu6mPlayer(Copl *newopl) : CPlayer(newopl), song_data(0) + Cu6mPlayer(Copl *newopl) : CPlayer(newopl), song_data(0) { }; - ~Cu6mPlayer() + ~Cu6mPlayer() { - if(song_data) { delete[] song_data; song_data = 0; } + if(song_data) delete[] song_data; }; - bool load(VFSFile &fd, const CFileProvider &fp); - bool update(); - void rewind(int subsong); - float getrefresh(); + bool load(const std::string &filename, const CFileProvider &fp); + bool update(); + void rewind(int subsong); + float getrefresh(); - std::string gettype() + std::string gettype() { - return std::string("Ultima 6 Music"); + return std::string("Ultima 6 Music"); }; - protected: - - struct byte_pair - { - unsigned char lo; - unsigned char hi; - }; - - struct subsong_info // information about a subsong - { - int continue_pos; - int subsong_repetitions; - int subsong_start; - }; - - struct dict_entry // dictionary entry - { - unsigned char root; - int codeword; - }; - - struct data_block // - { - long size; - unsigned char *data; - }; - - class MyDict + protected: + + struct byte_pair + { + unsigned char lo; + unsigned char hi; + }; + + struct subsong_info // information about a subsong + { + int continue_pos; + int subsong_repetitions; + int subsong_start; + }; + + struct dict_entry // dictionary entry + { + unsigned char root; + int codeword; + }; + + struct data_block // + { + long size; + unsigned char *data; + }; + + class MyDict { - private: - // The actual number of dictionary entries allocated - // is (dictionary_size-256), because there are 256 roots - // that do not need to be stored. - int contains; // number of entries currently in the dictionary - int dict_size; // max number of entries that will fit into the dictionary - dict_entry* dictionary; - - public: - MyDict(); // use dictionary size of 4096 - MyDict(int); // let the caller specify a dictionary size + private: + // The actual number of dictionary entries allocated + // is (dictionary_size-256), because there are 256 roots + // that do not need to be stored. + int contains; // number of entries currently in the dictionary + int dict_size; // max number of entries that will fit into the dictionary + dict_entry* dictionary; + + public: + MyDict(); // use dictionary size of 4096 + MyDict(int); // let the caller specify a dictionary size ~MyDict(); - void reset(); // re-initializes the dictionary - void add(unsigned char, int); - unsigned char get_root(int); - int get_codeword(int); + void reset(); // re-initializes the dictionary + void add(unsigned char, int); + unsigned char get_root(int); + int get_codeword(int); }; - // class variables - long played_ticks; - - unsigned char* song_data; // the uncompressed .m file (the "song") - bool driver_active; // flag to prevent reentrancy - bool songend; // indicates song end - int song_pos; // current offset within the song - int loop_position; // position of the loop point - int read_delay; // delay (in timer ticks) before further song data is read - std::stack<subsong_info> subsong_stack; - - int instrument_offsets[9]; // offsets of the adlib instrument data - // vibrato ("vb") - unsigned char vb_current_value[9]; - unsigned char vb_double_amplitude[9]; - unsigned char vb_multiplier[9]; - unsigned char vb_direction_flag[9]; - // mute factor ("mf") = not(volume) - unsigned char carrier_mf[9]; - signed char carrier_mf_signed_delta[9]; - unsigned char carrier_mf_mod_delay_backup[9]; - unsigned char carrier_mf_mod_delay[9]; - // frequency - byte_pair channel_freq[9]; // adlib freq settings for each channel - signed char channel_freq_signed_delta[9]; - - // protected functions used by update() - void command_loop(); - unsigned char read_song_byte(); - signed char read_signed_song_byte(); - void dec_clip(int&); - byte_pair expand_freq_byte(unsigned char); - void set_adlib_freq(int channel,byte_pair freq_word); - void set_adlib_freq_no_update(int channel,byte_pair freq_word); - void set_carrier_mf(int channel,unsigned char mute_factor); - void set_modulator_mf(int channel,unsigned char mute_factor); - void freq_slide(int channel); - void vibrato(int channel); - void mf_slide(int channel); - - void command_0(int channel); - void command_1(int channel); - void command_2(int channel); - void command_3(int channel); - void command_4(int channel); - void command_5(int channel); - void command_6(int channel); - void command_7(int channel); - void command_81(); - void command_82(); - void command_83(); - void command_85(); - void command_86(); - void command_E(); - void command_F(); - - void out_adlib(unsigned char adlib_register, unsigned char adlib_data); - void out_adlib_opcell(int channel, bool carrier, unsigned char adlib_register, unsigned char out_byte); - - // protected functions used by load() - bool lzw_decompress(data_block source, data_block dest); - int get_next_codeword (long& bits_read, unsigned char *source, int codeword_size); - void output_root(unsigned char root, unsigned char *destination, long& position); - void get_string(int codeword, MyDict& dictionary, std::stack<unsigned char>& root_stack); + // class variables + long played_ticks; + + unsigned char* song_data; // the uncompressed .m file (the "song") + bool driver_active; // flag to prevent reentrancy + bool songend; // indicates song end + int song_pos; // current offset within the song + int loop_position; // position of the loop point + int read_delay; // delay (in timer ticks) before further song data is read + std::stack<subsong_info> subsong_stack; + + int instrument_offsets[9]; // offsets of the adlib instrument data + // vibrato ("vb") + unsigned char vb_current_value[9]; + unsigned char vb_double_amplitude[9]; + unsigned char vb_multiplier[9]; + unsigned char vb_direction_flag[9]; + // mute factor ("mf") = not(volume) + unsigned char carrier_mf[9]; + signed char carrier_mf_signed_delta[9]; + unsigned char carrier_mf_mod_delay_backup[9]; + unsigned char carrier_mf_mod_delay[9]; + // frequency + byte_pair channel_freq[9]; // adlib freq settings for each channel + signed char channel_freq_signed_delta[9]; + + // protected functions used by update() + void command_loop(); + unsigned char read_song_byte(); + signed char read_signed_song_byte(); + void dec_clip(int&); + byte_pair expand_freq_byte(unsigned char); + void set_adlib_freq(int channel,byte_pair freq_word); + void set_adlib_freq_no_update(int channel,byte_pair freq_word); + void set_carrier_mf(int channel,unsigned char mute_factor); + void set_modulator_mf(int channel,unsigned char mute_factor); + void freq_slide(int channel); + void vibrato(int channel); + void mf_slide(int channel); + + void command_0(int channel); + void command_1(int channel); + void command_2(int channel); + void command_3(int channel); + void command_4(int channel); + void command_5(int channel); + void command_6(int channel); + void command_7(int channel); + void command_81(); + void command_82(); + void command_83(); + void command_85(); + void command_86(); + void command_E(); + void command_F(); + + void out_adlib(unsigned char adlib_register, unsigned char adlib_data); + void out_adlib_opcell(int channel, bool carrier, unsigned char adlib_register, unsigned char out_byte); + + // protected functions used by load() + bool lzw_decompress(data_block source, data_block dest); + int get_next_codeword (long& bits_read, unsigned char *source, int codeword_size); + void output_root(unsigned char root, unsigned char *destination, long& position); + void get_string(int codeword, MyDict& dictionary, std::stack<unsigned char>& root_stack); }; + diff --git a/src/adplug/core/xad.cc b/src/adplug/core/xad.cc index f5b406c..a84ed43 100644 --- a/src/adplug/core/xad.cc +++ b/src/adplug/core/xad.cc @@ -24,63 +24,52 @@ /* -------- Public Methods -------------------------------- */ -CxadPlayer::CxadPlayer (Copl * newopl):CPlayer (newopl) +CxadPlayer::CxadPlayer(Copl * newopl) : CPlayer(newopl) { tune = 0; } -CxadPlayer::~CxadPlayer () +CxadPlayer::~CxadPlayer() { if (tune) - { - delete[]tune; - tune = 0; - } + delete [] tune; } -bool -CxadPlayer::load (VFSFile & fd, const CFileProvider & fp) +bool CxadPlayer::load(const std::string &filename, const CFileProvider &fp) { - binistream *f = fp.open (fd); - if (!f) - return false; + binistream *f = fp.open(filename); if(!f) return false; bool ret = false; // load header - xad.id = f->readInt (4); - f->readString (xad.title, 36); - f->readString (xad.author, 36); - xad.fmt = f->readInt (2); - xad.speed = f->readInt (1); - xad.reserved_a = f->readInt (1); + xad.id = f->readInt(4); + f->readString(xad.title, 36); + f->readString(xad.author, 36); + xad.fmt = f->readInt(2); + xad.speed = f->readInt(1); + xad.reserved_a = f->readInt(1); // 'XAD!' - signed ? - if (xad.id != 0x21444158) - { - fp.close (f); - return false; - } + if(xad.id != 0x21444158) { fp.close(f); return false; } // get file size - tune_size = fp.filesize (f) - 80; + tune_size = fp.filesize(f) - 80; // load() - tune = new unsigned char[tune_size]; - f->readString ((char *) tune, tune_size); - fp.close (f); + tune = new unsigned char [tune_size]; + f->readString((char *)tune, tune_size); + fp.close(f); - ret = xadplayer_load (); + ret = xadplayer_load(); if (ret) - rewind (0); + rewind(0); return ret; } -void -CxadPlayer::rewind (int subsong) +void CxadPlayer::rewind(int subsong) { - opl->init (); + opl->init(); plr.speed = xad.speed; plr.speed_counter = 1; @@ -88,15 +77,14 @@ CxadPlayer::rewind (int subsong) plr.looping = 0; // rewind() - xadplayer_rewind (subsong); + xadplayer_rewind(subsong); #ifdef DEBUG - AdPlug_LogWrite ("-----------\n"); + AdPlug_LogWrite("-----------\n"); #endif } -bool -CxadPlayer::update () +bool CxadPlayer::update() { if (--plr.speed_counter) goto update_end; @@ -104,52 +92,49 @@ CxadPlayer::update () plr.speed_counter = plr.speed; // update() - xadplayer_update (); + xadplayer_update(); update_end: return (plr.playing && (!plr.looping)); } -float -CxadPlayer::getrefresh () +float CxadPlayer::getrefresh() { - return xadplayer_getrefresh (); + return xadplayer_getrefresh(); } -std::string CxadPlayer::gettype () +std::string CxadPlayer::gettype() { - return xadplayer_gettype (); + return xadplayer_gettype(); } -std::string CxadPlayer::gettitle () +std::string CxadPlayer::gettitle() { - return xadplayer_gettitle (); + return xadplayer_gettitle(); } -std::string CxadPlayer::getauthor () +std::string CxadPlayer::getauthor() { - return xadplayer_getauthor (); + return xadplayer_getauthor(); } -std::string CxadPlayer::getinstrument (unsigned int i) +std::string CxadPlayer::getinstrument(unsigned int i) { - return xadplayer_getinstrument (i); + return xadplayer_getinstrument(i); } -unsigned int -CxadPlayer::getinstruments () +unsigned int CxadPlayer::getinstruments() { - return xadplayer_getinstruments (); + return xadplayer_getinstruments(); } /* -------- Protected Methods ------------------------------- */ -void -CxadPlayer::opl_write (int reg, int val) +void CxadPlayer::opl_write(int reg, int val) { adlib[reg] = val; #ifdef DEBUG - AdPlug_LogWrite ("[ %02X ] = %02X\n", reg, val); + AdPlug_LogWrite("[ %02X ] = %02X\n",reg,val); #endif - opl->write (reg, val); + opl->write(reg,val); } diff --git a/src/adplug/core/xad.h b/src/adplug/core/xad.h index 8dd8912..68401fa 100644 --- a/src/adplug/core/xad.h +++ b/src/adplug/core/xad.h @@ -32,10 +32,10 @@ public: CxadPlayer(Copl * newopl); ~CxadPlayer(); - bool load(VFSFile &fd, const CFileProvider &fp); - bool update(); - void rewind(int subsong); - float getrefresh(); + bool load(const std::string &filename, const CFileProvider &fp); + bool update(); + void rewind(int subsong); + float getrefresh(); std::string gettype(); std::string gettitle(); @@ -44,33 +44,33 @@ public: unsigned int getinstruments(); protected: - virtual void xadplayer_rewind(int subsong) = 0; - virtual bool xadplayer_load() = 0; - virtual void xadplayer_update() = 0; - virtual float xadplayer_getrefresh() = 0; - virtual std::string xadplayer_gettype() = 0; - virtual std::string xadplayer_gettitle() - { - return std::string(xad.title); - } - virtual std::string xadplayer_getauthor() - { - return std::string(xad.author); - } - virtual std::string xadplayer_getinstrument(unsigned int i) - { - return std::string(""); - } - virtual unsigned int xadplayer_getinstruments() - { - return 0; - } - - enum { HYP=1, PSI, FLASH, BMF, RAT, HYBRID }; + virtual void xadplayer_rewind(int subsong) = 0; + virtual bool xadplayer_load() = 0; + virtual void xadplayer_update() = 0; + virtual float xadplayer_getrefresh() = 0; + virtual std::string xadplayer_gettype() = 0; + virtual std::string xadplayer_gettitle() + { + return std::string(xad.title); + } + virtual std::string xadplayer_getauthor() + { + return std::string(xad.author); + } + virtual std::string xadplayer_getinstrument(unsigned int i) + { + return std::string(""); + } + virtual unsigned int xadplayer_getinstruments() + { + return 0; + } + + enum { HYP=1, PSI, FLASH, BMF, RAT, HYBRID }; struct xad_header { - unsigned long id; + unsigned long id; char title[36]; char author[36]; unsigned short fmt; diff --git a/src/adplug/core/xsm.cc b/src/adplug/core/xsm.cc index e943769..34c6b29 100644 --- a/src/adplug/core/xsm.cc +++ b/src/adplug/core/xsm.cc @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -23,87 +23,72 @@ #include "xsm.h" -CxsmPlayer::CxsmPlayer (Copl * newopl):CPlayer (newopl), music (0) +CxsmPlayer::CxsmPlayer(Copl *newopl) + : CPlayer(newopl), music(0) { } -CxsmPlayer::~CxsmPlayer () +CxsmPlayer::~CxsmPlayer() { - if (music) - { - delete[]music; - music = 0; - } + if(music) delete [] music; } -bool -CxsmPlayer::load (VFSFile & fd, const CFileProvider & fp) +bool CxsmPlayer::load(const std::string &filename, const CFileProvider &fp) { - binistream *f = fp.open (fd); - if (!f) - return false; - char id[6]; - int i, j; + binistream *f = fp.open(filename); if(!f) return false; + char id[6]; + int i, j; // check if header matches - f->readString (id, 6); - songlen = f->readInt (2); - if (strncmp (id, "ofTAZ!", 6) || songlen > 3200) - { - fp.close (f); - return false; - } + f->readString(id, 6); songlen = f->readInt(2); + if(strncmp(id, "ofTAZ!", 6) || songlen > 3200) { fp.close(f); return false; } // read and set instruments - for (i = 0; i < 9; i++) - { - opl->write (0x20 + op_table[i], f->readInt (1)); - opl->write (0x23 + op_table[i], f->readInt (1)); - opl->write (0x40 + op_table[i], f->readInt (1)); - opl->write (0x43 + op_table[i], f->readInt (1)); - opl->write (0x60 + op_table[i], f->readInt (1)); - opl->write (0x63 + op_table[i], f->readInt (1)); - opl->write (0x80 + op_table[i], f->readInt (1)); - opl->write (0x83 + op_table[i], f->readInt (1)); - opl->write (0xe0 + op_table[i], f->readInt (1)); - opl->write (0xe3 + op_table[i], f->readInt (1)); - opl->write (0xc0 + op_table[i], f->readInt (1)); - f->ignore (5); + for(i = 0; i < 9; i++) { + opl->write(0x20 + op_table[i], f->readInt(1)); + opl->write(0x23 + op_table[i], f->readInt(1)); + opl->write(0x40 + op_table[i], f->readInt(1)); + opl->write(0x43 + op_table[i], f->readInt(1)); + opl->write(0x60 + op_table[i], f->readInt(1)); + opl->write(0x63 + op_table[i], f->readInt(1)); + opl->write(0x80 + op_table[i], f->readInt(1)); + opl->write(0x83 + op_table[i], f->readInt(1)); + opl->write(0xe0 + op_table[i], f->readInt(1)); + opl->write(0xe3 + op_table[i], f->readInt(1)); + opl->write(0xc0 + op_table[i], f->readInt(1)); + f->ignore(5); } // read song data - music = new char[songlen * 9]; - for (i = 0; i < 9; i++) - for (j = 0; j < songlen; j++) - music[j * 9 + i] = f->readInt (1); + music = new char [songlen * 9]; + for(i = 0; i < 9; i++) + for(j = 0; j < songlen; j++) + music[j * 9 + i] = f->readInt(1); // success - fp.close (f); - rewind (0); + fp.close(f); + rewind(0); return true; } -bool -CxsmPlayer::update () +bool CxsmPlayer::update() { int c; - if (notenum >= songlen) - { + if(notenum >= songlen) { songend = true; notenum = last = 0; } - for (c = 0; c < 9; c++) - if (music[notenum * 9 + c] != music[last * 9 + c]) - opl->write (0xb0 + c, 0); + for(c = 0; c < 9; c++) + if(music[notenum * 9 + c] != music[last * 9 + c]) + opl->write(0xb0 + c, 0); - for (c = 0; c < 9; c++) - { - if (music[notenum * 9 + c]) - play_note (c, music[notenum * 9 + c] % 12, music[notenum * 9 + c] / 12); + for(c = 0; c < 9; c++) { + if(music[notenum * 9 + c]) + play_note(c, music[notenum * 9 + c] % 12, music[notenum * 9 + c] / 12); else - play_note (c, 0, 0); + play_note(c, 0, 0); } last = notenum; @@ -111,26 +96,22 @@ CxsmPlayer::update () return !songend; } -void -CxsmPlayer::rewind (int subsong) +void CxsmPlayer::rewind(int subsong) { notenum = last = 0; songend = false; } -float -CxsmPlayer::getrefresh () +float CxsmPlayer::getrefresh() { return 5.0f; } -void -CxsmPlayer::play_note (int c, int note, int octv) +void CxsmPlayer::play_note(int c, int note, int octv) { int freq = note_table[note]; - if (!note && !octv) - freq = 0; - opl->write (0xa0 + c, freq & 0xff); - opl->write (0xb0 + c, (freq / 0xff) | 32 | (octv * 4)); + if(!note && !octv) freq = 0; + opl->write(0xa0 + c, freq & 0xff); + opl->write(0xb0 + c, (freq / 0xff) | 32 | (octv * 4)); } diff --git a/src/adplug/core/xsm.h b/src/adplug/core/xsm.h index 714a0af..e7cf7c7 100644 --- a/src/adplug/core/xsm.h +++ b/src/adplug/core/xsm.h @@ -1,17 +1,17 @@ /* * Adplug - Replayer for many OPL2/OPL3 audio file formats. * Copyright (C) 1999 - 2003 Simon Peter, <dn.tlp@gmx.net>, et al. - * + * * 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; either * version 2.1 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 * 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 Street, Fifth Floor, Boston, MA 02110-1301 USA @@ -29,7 +29,7 @@ public: CxsmPlayer(Copl *newopl); ~CxsmPlayer(); - bool load(VFSFile &fd, const CFileProvider &fp); + bool load(const std::string &filename, const CFileProvider &fp); bool update(); void rewind(int subsong); float getrefresh(); @@ -37,10 +37,10 @@ public: std::string gettype() { return std::string("eXtra Simple Music"); } private: - unsigned short songlen; - char *music; - unsigned int last, notenum; - bool songend; + unsigned short songlen; + char *music; + unsigned int last, notenum; + bool songend; void play_note(int c, int note, int octv); }; diff --git a/src/alarm/alarm.cc b/src/alarm/alarm.cc index 80a97b3..2eadfca 100644 --- a/src/alarm/alarm.cc +++ b/src/alarm/alarm.cc @@ -28,6 +28,7 @@ #include <assert.h> #include <math.h> +#define AUD_PLUGIN_GLIB_ONLY #include <libaudcore/drct.h> #include <libaudcore/i18n.h> #include <libaudcore/interface.h> @@ -189,7 +190,7 @@ static GtkWidget *lookup_widget(GtkWidget *w, const char *name) * the callback function that is called when the save button is * pressed saves configuration to ~/.bmp/alarmconfig */ -static void alarm_save(void) +static void alarm_save() { int daynum = 0; // used to identify day number @@ -266,7 +267,7 @@ static void alarm_save(void) /* * read the current configuration from the file */ -static void alarm_read_config(void) +static void alarm_read_config() { int daynum = 0; // used for day number @@ -305,7 +306,7 @@ static void alarm_read_config(void) /* * displays the configuration window and opens the config file. */ -static void *alarm_make_config_widget(void) +static void *alarm_make_config_widget() { int daynum = 0; // used to loop days GtkWidget *w; @@ -382,8 +383,8 @@ static void *alarm_make_config_widget(void) alarm_conf.day[daynum].spin_min = GTK_SPIN_BUTTON(w); gtk_spin_button_set_value(alarm_conf.day[daynum].spin_min, alarm_conf.default_min); - gtk_widget_set_sensitive((GtkWidget *)alarm_conf.day[daynum].spin_hr, FALSE); - gtk_widget_set_sensitive((GtkWidget *)alarm_conf.day[daynum].spin_min, FALSE); + gtk_widget_set_sensitive((GtkWidget *)alarm_conf.day[daynum].spin_hr, false); + gtk_widget_set_sensitive((GtkWidget *)alarm_conf.day[daynum].spin_min, false); } else { @@ -395,8 +396,8 @@ static void *alarm_make_config_widget(void) alarm_conf.day[daynum].spin_min = GTK_SPIN_BUTTON(w); gtk_spin_button_set_value(alarm_conf.day[daynum].spin_min, alarm_conf.day[daynum].min); - gtk_widget_set_sensitive((GtkWidget *)alarm_conf.day[daynum].spin_hr, TRUE); - gtk_widget_set_sensitive((GtkWidget *)alarm_conf.day[daynum].spin_min, TRUE); + gtk_widget_set_sensitive((GtkWidget *)alarm_conf.day[daynum].spin_hr, true); + gtk_widget_set_sensitive((GtkWidget *)alarm_conf.day[daynum].spin_min, true); } } @@ -444,27 +445,27 @@ static void on_day_def_toggled(GtkToggleButton *togglebutton, void * user_data, if(w == nullptr) return; - if(gtk_toggle_button_get_active(togglebutton) == TRUE) + if(gtk_toggle_button_get_active(togglebutton) == true) { gtk_spin_button_set_value(GTK_SPIN_BUTTON(w), alarm_conf.default_hour); - gtk_widget_set_sensitive(w, FALSE); + gtk_widget_set_sensitive(w, false); } else { gtk_spin_button_set_value(GTK_SPIN_BUTTON(w), alarm_conf.day[daynum].hour); - gtk_widget_set_sensitive(w, TRUE); + gtk_widget_set_sensitive(w, true); } w = lookup_widget(config_notebook, day_m[daynum]); - if(gtk_toggle_button_get_active(togglebutton) == TRUE) + if(gtk_toggle_button_get_active(togglebutton) == true) { gtk_spin_button_set_value(GTK_SPIN_BUTTON(w), alarm_conf.default_min); - gtk_widget_set_sensitive(w, FALSE); + gtk_widget_set_sensitive(w, false); } else { gtk_spin_button_set_value(GTK_SPIN_BUTTON(w), alarm_conf.day[daynum].min); - gtk_widget_set_sensitive(w, TRUE); + gtk_widget_set_sensitive(w, true); } } @@ -637,7 +638,7 @@ void alarm_stop_cancel(GtkWidget *w, void * data) { AUDDBG("alarm_stop_cancel\n"); if (pthread_cancel(stop.tid) == 0) - stop.is_valid = FALSE; + stop.is_valid = false; } /* the main alarm thread */ @@ -655,10 +656,10 @@ static gboolean alarm_timeout (void * unused) /* already went off? */ if (timenow < play_start + 60) - return TRUE; + return true; if(alarm_conf.day[today].flags & ALARM_OFF) - return TRUE; + return true; else { /* set the alarm_h and alarm_m for today, if not default */ @@ -679,9 +680,9 @@ static gboolean alarm_timeout (void * unused) AUDDBG("Checking time (%d:%d)\n", currtime->tm_hour, currtime->tm_min); if((currtime->tm_hour != alarm_h) || (currtime->tm_min != alarm_m)) - return TRUE; + return true; - if(cmd_on == TRUE) + if(cmd_on == true) { String cmdstr = aud_get_str ("alarm", "cmdstr"); AUDDBG("Executing %s, cmd_on is true\n", (const char *) cmdstr); @@ -689,13 +690,13 @@ static gboolean alarm_timeout (void * unused) AUDDBG("Executing %s failed\n", (const char *) cmdstr); } - gboolean started = FALSE; + gboolean started = false; String playlist = aud_get_str ("alarm", "playlist"); if (playlist[0]) { aud_drct_pl_open (playlist); - started = TRUE; + started = true; } if(fading) @@ -730,7 +731,7 @@ static gboolean alarm_timeout (void * unused) aud_drct_play(); } - if(alarm_conf.reminder_on == TRUE) + if(alarm_conf.reminder_on == true) { String reminder_msg = aud_get_str ("alarm", "reminder_msg"); GtkWidget *reminder_dialog; @@ -747,7 +748,7 @@ static gboolean alarm_timeout (void * unused) * this means that the dialog doesnt get shown until the volume has * finished fading though !, so thats something else to fix */ - if(stop_on == TRUE) + if(stop_on == true) { alarm_dialog = create_alarm_dialog(); @@ -756,7 +757,7 @@ static gboolean alarm_timeout (void * unused) AUDDBG("Created wakeup dialog and started stop thread\n"); } - return TRUE; + return true; } static void alarm_configure () @@ -802,7 +803,7 @@ void AlarmPlugin::cleanup () if (stop.is_valid) { pthread_cancel(stop.tid); - stop.is_valid = FALSE; + stop.is_valid = false; } } diff --git a/src/alarm/interface.cc b/src/alarm/interface.cc index a396d92..4b54ab5 100644 --- a/src/alarm/interface.cc +++ b/src/alarm/interface.cc @@ -23,9 +23,8 @@ #include "callbacks.h" -const char *help[] = -{ - N_("Time\n" +static const char help_text[] = + N_("Time\n" " Alarm at:\n" " The time for the alarm to come on.\n\n" @@ -40,9 +39,9 @@ const char *help[] = " Time:\n" " Choose the time for the alarm on each day,\n" " or select the toggle button to use the default\n" - " time.\n\n\n"), + " time.\n\n\n" - N_("Volume\n" + "Volume\n" " Fading:\n" " Fade the volume up to the chosen volume\n" " for this amount of time.\n\n" @@ -57,9 +56,9 @@ const char *help[] = "Options:\n" " Additional Command:\n" - " Run this command at the alarm time.\n\n"), + " Run this command at the alarm time.\n\n" - N_(" Playlist:\n" + " Playlist:\n" " Load this playlist. If no playlist\n" " is given, the current one will be used.\n" " The URL of an mp3/ogg stream\n" @@ -67,13 +66,10 @@ const char *help[] = " Reminder:\n" " Display a reminder when the alarm goes off.\n" - " Type the reminder in the box and turn on the\n" - " toggle button if you want it to be shown."), - - nullptr -}; + " Type the reminder in the input field and enable\n" + " the checkbox if you want it to be shown."); -GtkWidget *create_alarm_dialog (void) +GtkWidget *create_alarm_dialog () { GtkWidget *alarm_dialog; @@ -113,7 +109,7 @@ static void file_set_cb (GtkFileChooserButton *button, void * entry) g_free (uri); } -GtkWidget *create_config_notebook (void) +GtkWidget *create_config_notebook () { /* General */ GtkWidget *notebook; @@ -129,8 +125,8 @@ GtkWidget *create_config_notebook (void) GtkWidget *checkbutton; GtkWidget *widget[21]; - const char *weekdays[] = { _("Monday"), _("Tuesday"), _("Wednesday"), - _("Thursday"), _("Friday"), _("Saturday"), _("Sunday") }; + const char *weekdays[] = { N_("Monday"), N_("Tuesday"), N_("Wednesday"), + N_("Thursday"), N_("Friday"), N_("Saturday"), N_("Sunday") }; const char *day_cb[] = { "mon_cb", "tue_cb", "wed_cb", "thu_cb", "fri_cb", "sat_cb", "sun_cb" }; @@ -160,7 +156,6 @@ GtkWidget *create_config_notebook (void) /* Page 5 */ GtkWidget *view, *scrolled_window; GtkTextBuffer *text_buffer; - char *help_text; /* General */ @@ -170,7 +165,7 @@ GtkWidget *create_config_notebook (void) /* Page 1 */ frame = gtk_frame_new (_("Time")); gtk_container_set_border_width (GTK_CONTAINER (frame), 6); - grid = gtk_table_new (0, 0, FALSE); + grid = gtk_table_new (0, 0, false); gtk_table_set_col_spacings (GTK_TABLE (grid), 6); gtk_table_set_row_spacings (GTK_TABLE (grid), 6); gtk_container_set_border_width (GTK_CONTAINER (grid), 6); @@ -182,8 +177,8 @@ GtkWidget *create_config_notebook (void) alarm_h_spin = gtk_spin_button_new (adjustment, 1, 0); g_object_set_data (G_OBJECT (notebook), "alarm_h_spin", alarm_h_spin); gtk_spin_button_set_update_policy (GTK_SPIN_BUTTON (alarm_h_spin), GTK_UPDATE_IF_VALID); - gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (alarm_h_spin), TRUE); - gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (alarm_h_spin), TRUE); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (alarm_h_spin), true); + gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (alarm_h_spin), true); gtk_table_attach (GTK_TABLE (grid), alarm_h_spin, 1, 2, 0, 1, GTK_FILL, GTK_FILL, 0, 0); label = gtk_label_new (":"); @@ -193,8 +188,8 @@ GtkWidget *create_config_notebook (void) alarm_m_spin = gtk_spin_button_new (adjustment, 1, 0); g_object_set_data (G_OBJECT (notebook), "alarm_m_spin", alarm_m_spin); gtk_spin_button_set_update_policy (GTK_SPIN_BUTTON (alarm_m_spin), GTK_UPDATE_IF_VALID); - gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (alarm_m_spin), TRUE); - gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (alarm_m_spin), TRUE); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (alarm_m_spin), true); + gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (alarm_m_spin), true); gtk_table_attach (GTK_TABLE (grid), alarm_m_spin, 3, 4, 0, 1, GTK_FILL, GTK_FILL, 0, 0); label = gtk_label_new (_("h")); @@ -208,8 +203,8 @@ GtkWidget *create_config_notebook (void) stop_h_spin = gtk_spin_button_new (adjustment, 1, 0); g_object_set_data (G_OBJECT (notebook), "stop_h_spin", stop_h_spin); gtk_spin_button_set_update_policy (GTK_SPIN_BUTTON (stop_h_spin), GTK_UPDATE_IF_VALID); - gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (stop_h_spin), TRUE); - gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (stop_h_spin), TRUE); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (stop_h_spin), true); + gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (stop_h_spin), true); gtk_table_attach (GTK_TABLE (grid), stop_h_spin, 1, 2, 1, 2, GTK_FILL, GTK_FILL, 0, 0); label = gtk_label_new (_("hours")); @@ -219,8 +214,8 @@ GtkWidget *create_config_notebook (void) stop_m_spin = gtk_spin_button_new (adjustment, 1, 0); g_object_set_data (G_OBJECT (notebook), "stop_m_spin", stop_m_spin); gtk_spin_button_set_update_policy (GTK_SPIN_BUTTON (stop_m_spin), GTK_UPDATE_IF_VALID); - gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (stop_m_spin), TRUE); - gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (stop_m_spin), TRUE); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (stop_m_spin), true); + gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (stop_m_spin), true); gtk_table_attach (GTK_TABLE (grid), stop_m_spin, 3, 4, 1, 2, GTK_FILL, GTK_FILL, 0, 0); label = gtk_label_new (_("minutes")); @@ -234,7 +229,7 @@ GtkWidget *create_config_notebook (void) /* Page 2 */ frame = gtk_frame_new (_("Choose the days for the alarm to come on")); gtk_container_set_border_width (GTK_CONTAINER (frame), 6); - grid = gtk_table_new (0, 0, FALSE); + grid = gtk_table_new (0, 0, false); gtk_table_set_col_spacings (GTK_TABLE (grid), 6); gtk_table_set_row_spacings (GTK_TABLE (grid), 6); gtk_container_set_border_width (GTK_CONTAINER (grid), 6); @@ -247,18 +242,18 @@ GtkWidget *create_config_notebook (void) for (i = 0; i < 7; i ++) { - widget[i] = gtk_check_button_new_with_label (weekdays[i]); + widget[i] = gtk_check_button_new_with_label (_(weekdays[i])); g_object_set_data (G_OBJECT (notebook), day_cb[i], widget[i]); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget[i]), TRUE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget[i]), true); gtk_table_attach (GTK_TABLE (grid), widget[i], 0, 1, i + 1, i + 2, GTK_FILL, GTK_FILL, 0, 0); } - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget[6]), FALSE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget[6]), false); for (i = 0; i < 7; i ++) { checkbutton = gtk_check_button_new_with_label (_("Default")); g_object_set_data (G_OBJECT (notebook), day_def[i], checkbutton); - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton), TRUE); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton), true); g_signal_connect (checkbutton, "toggled", G_CALLBACK (cb_def[i]), nullptr); gtk_table_attach (GTK_TABLE (grid), checkbutton, 1, 2, i + 1, i + 2, GTK_FILL, GTK_FILL, 0, 0); } @@ -291,8 +286,8 @@ GtkWidget *create_config_notebook (void) /* Page 3 */ - vbox = gtk_vbox_new (FALSE, 6); - hbox = gtk_hbox_new (FALSE, 6); + vbox = gtk_vbox_new (false, 6); + hbox = gtk_hbox_new (false, 6); frame = gtk_frame_new (_("Fading")); gtk_container_set_border_width (GTK_CONTAINER (frame), 6); @@ -300,77 +295,77 @@ GtkWidget *create_config_notebook (void) adjustment = (GtkAdjustment *) gtk_adjustment_new (120, 0, 3600, 1, 10, 0); fading_spin = gtk_spin_button_new (adjustment, 1, 0); g_object_set_data (G_OBJECT (notebook), "fading_spin", fading_spin); - gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (fading_spin), TRUE); + gtk_spin_button_set_numeric (GTK_SPIN_BUTTON (fading_spin), true); gtk_spin_button_set_update_policy (GTK_SPIN_BUTTON (fading_spin), GTK_UPDATE_IF_VALID); label = gtk_label_new (_("seconds")); - gtk_box_pack_start (GTK_BOX (hbox), fading_spin, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (hbox), fading_spin, true, true, 0); + gtk_box_pack_start (GTK_BOX (hbox), label, false, false, 0); gtk_container_add (GTK_CONTAINER (frame), hbox); - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (vbox), frame, false, false, 0); frame = gtk_frame_new (_("Volume")); - vbox2 = gtk_vbox_new (FALSE, 6); + vbox2 = gtk_vbox_new (false, 6); gtk_container_set_border_width (GTK_CONTAINER (frame), 6); gtk_container_set_border_width (GTK_CONTAINER (vbox2), 6); label = gtk_label_new (_("Start at")); - gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (vbox2), label, false, false, 0); quiet_vol_scale = gtk_hscale_new ((GtkAdjustment *) gtk_adjustment_new (20, 0, 100, 1, 5, 0)); g_object_set_data (G_OBJECT (notebook), "quiet_vol_scale", quiet_vol_scale); gtk_scale_set_value_pos (GTK_SCALE (quiet_vol_scale), GTK_POS_RIGHT); gtk_scale_set_digits (GTK_SCALE (quiet_vol_scale), 0); label = gtk_label_new ("%"); - hbox2 = gtk_hbox_new (FALSE, 6); - gtk_box_pack_start (GTK_BOX (hbox2), quiet_vol_scale, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (vbox2), hbox2, FALSE, FALSE, 0); + hbox2 = gtk_hbox_new (false, 6); + gtk_box_pack_start (GTK_BOX (hbox2), quiet_vol_scale, true, true, 0); + gtk_box_pack_start (GTK_BOX (hbox2), label, false, false, 0); + gtk_box_pack_start (GTK_BOX (vbox2), hbox2, false, false, 0); separator = gtk_hseparator_new (); - gtk_box_pack_start (GTK_BOX (vbox2), separator, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (vbox2), separator, false, false, 0); label = gtk_label_new (_("Final")); - gtk_box_pack_start (GTK_BOX (vbox2), label, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (vbox2), label, false, false, 0); vol_scale = gtk_hscale_new ((GtkAdjustment *) gtk_adjustment_new (80, 0, 100, 1, 5, 0)); g_object_set_data (G_OBJECT (notebook), "vol_scale", vol_scale); gtk_scale_set_value_pos (GTK_SCALE (vol_scale), GTK_POS_RIGHT); gtk_scale_set_digits (GTK_SCALE (vol_scale), 0); label = gtk_label_new ("%"); - hbox2 = gtk_hbox_new (FALSE, 6); - gtk_box_pack_start (GTK_BOX (hbox2), vol_scale, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (vbox2), hbox2, FALSE, FALSE, 0); + hbox2 = gtk_hbox_new (false, 6); + gtk_box_pack_start (GTK_BOX (hbox2), vol_scale, true, true, 0); + gtk_box_pack_start (GTK_BOX (hbox2), label, false, false, 0); + gtk_box_pack_start (GTK_BOX (vbox2), hbox2, false, false, 0); current_button = gtk_button_new_with_label (_("Current")); g_signal_connect (current_button, "clicked", G_CALLBACK (alarm_current_volume), nullptr); - gtk_box_pack_start (GTK_BOX (vbox2), current_button, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (vbox2), current_button, false, false, 0); gtk_container_add (GTK_CONTAINER (frame), vbox2); - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (vbox), frame, false, false, 0); label = gtk_label_new (_("Volume")); gtk_notebook_append_page (GTK_NOTEBOOK (notebook), vbox, label); /* Page 4 */ - vbox = gtk_vbox_new (FALSE, 6); + vbox = gtk_vbox_new (false, 6); frame = gtk_frame_new (_("Additional Command")); - hbox = gtk_hbox_new (FALSE, 6); + hbox = gtk_hbox_new (false, 6); gtk_container_set_border_width (GTK_CONTAINER (frame), 6); gtk_container_set_border_width (GTK_CONTAINER (hbox), 6); cmd_entry = gtk_entry_new (); g_object_set_data (G_OBJECT (notebook), "cmd_entry", cmd_entry); cmd_checkb = gtk_check_button_new_with_label (_("enable")); g_object_set_data (G_OBJECT (notebook), "cmd_checkb", cmd_checkb); - gtk_box_pack_start (GTK_BOX (hbox), cmd_entry, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (hbox), cmd_checkb, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (hbox), cmd_entry, true, true, 0); + gtk_box_pack_start (GTK_BOX (hbox), cmd_checkb, false, false, 0); gtk_container_add (GTK_CONTAINER (frame), hbox); - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (vbox), frame, false, false, 0); frame = gtk_frame_new (_("Playlist (optional)")); - hbox = gtk_hbox_new (FALSE, 6); + hbox = gtk_hbox_new (false, 6); gtk_container_set_border_width (GTK_CONTAINER (frame), 6); gtk_container_set_border_width (GTK_CONTAINER (hbox), 6); playlist_entry = gtk_entry_new (); @@ -378,23 +373,23 @@ GtkWidget *create_config_notebook (void) file_chooser_button = gtk_file_chooser_button_new (_("Select a playlist"), GTK_FILE_CHOOSER_ACTION_OPEN); g_signal_connect (file_chooser_button, "file-set", G_CALLBACK (file_set_cb), playlist_entry); - gtk_box_pack_start (GTK_BOX (hbox), playlist_entry, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (hbox), file_chooser_button, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (hbox), playlist_entry, true, true, 0); + gtk_box_pack_start (GTK_BOX (hbox), file_chooser_button, true, true, 0); gtk_container_add (GTK_CONTAINER (frame), hbox); - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (vbox), frame, false, false, 0); frame = gtk_frame_new (_("Reminder")); - hbox = gtk_hbox_new (FALSE, 6); + hbox = gtk_hbox_new (false, 6); gtk_container_set_border_width (GTK_CONTAINER (frame), 6); gtk_container_set_border_width (GTK_CONTAINER (hbox), 6); reminder_text = gtk_entry_new (); reminder_checkb = gtk_check_button_new_with_label (_("enable")); g_object_set_data (G_OBJECT (notebook), "reminder_text", reminder_text); g_object_set_data (G_OBJECT (notebook), "reminder_cb", reminder_checkb); - gtk_box_pack_start (GTK_BOX (hbox), reminder_text, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (hbox), reminder_checkb, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (hbox), reminder_text, true, true, 0); + gtk_box_pack_start (GTK_BOX (hbox), reminder_checkb, false, false, 0); gtk_container_add (GTK_CONTAINER (frame), hbox); - gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (vbox), frame, false, false, 0); label = gtk_label_new (_("Options")); gtk_notebook_append_page (GTK_NOTEBOOK (notebook), vbox, label); @@ -404,12 +399,10 @@ GtkWidget *create_config_notebook (void) frame = gtk_frame_new (_("What do these options mean?")); gtk_container_set_border_width (GTK_CONTAINER (frame), 6); view = gtk_text_view_new (); - gtk_text_view_set_editable (GTK_TEXT_VIEW (view), FALSE); - gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view), FALSE); + gtk_text_view_set_editable (GTK_TEXT_VIEW (view), false); + gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (view), false); text_buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (view)); - help_text = g_strconcat (_(help[0]), _(help[1]), _(help[2]), nullptr); - gtk_text_buffer_set_text (text_buffer, help_text, -1); - g_free (help_text); + gtk_text_buffer_set_text (text_buffer, _(help_text), -1); scrolled_window = gtk_scrolled_window_new (nullptr, nullptr); gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); diff --git a/src/alarm/interface.h b/src/alarm/interface.h index cea9457..998d39d 100644 --- a/src/alarm/interface.h +++ b/src/alarm/interface.h @@ -1,8 +1,8 @@ #ifndef __INTERFACE_H #define __INTERFACE_H -GtkWidget* create_alarm_dialog (void); -GtkWidget* create_config_notebook (void); +GtkWidget* create_alarm_dialog (); +GtkWidget* create_config_notebook (); GtkWidget* create_reminder_dialog (const char *reminder_msg); #endif diff --git a/src/albumart-qt/albumart.cc b/src/albumart-qt/albumart.cc index 3d53c48..df7720c 100644 --- a/src/albumart-qt/albumart.cc +++ b/src/albumart-qt/albumart.cc @@ -20,6 +20,7 @@ #include <QLabel> #include <QPixmap> +#define AUD_PLUGIN_QT_ONLY #include <libaudcore/drct.h> #include <libaudcore/i18n.h> #include <libaudcore/plugin.h> @@ -30,58 +31,106 @@ class AlbumArtQt : public GeneralPlugin { public: static constexpr PluginInfo info = { - N_("Album Art (Qt)"), + N_("Album Art"), PACKAGE }; constexpr AlbumArtQt () : GeneralPlugin (info, false) {} void * get_qt_widget (); +}; + +#define MARGIN 4 + +class ArtLabel : public QLabel { +public: + ArtLabel (QWidget * parent = 0, Qt::WindowFlags f = 0) : QLabel(parent, f) + { + init (); + } + + ArtLabel (const QString & text, QWidget * parent = 0, Qt::WindowFlags f = 0) : QLabel (text, parent, f) + { + init (); + } + + void update_art () + { + origPixmap = QPixmap (audqt::art_request_current (0, 0)); + origSize = origPixmap.size (); + drawArt (); + } + + void clear () + { + QLabel::clear (); + origPixmap = QPixmap (); + } + +protected: + virtual void resizeEvent (QResizeEvent * event) + { + QLabel::resizeEvent (event); + const QPixmap * pm = pixmap (); + + if ( ! origPixmap.isNull () && pm && ! pm->isNull () && + (size ().width () <= origSize.width () + MARGIN || + size ().height () <= origSize.height () + MARGIN || + pm->size ().width () != origSize.width () || + pm->size ().height () != origSize.height ())) + drawArt (); + } private: - static void update (void * unused, QLabel * widget); - static void clear (void * unused, QLabel * widget); - static void widget_cleanup (QObject * widget); + QPixmap origPixmap; + QSize origSize; + + void init () + { + clear (); + setMinimumSize (MARGIN + 1, MARGIN + 1); + setAlignment (Qt::AlignCenter); + } + + void drawArt () + { + if (origSize.width () <= size ().width () - MARGIN && + origSize.height () <= size ().height() - MARGIN) + setPixmap (origPixmap); + else + setPixmap (origPixmap.scaled (size ().width () - MARGIN, size ().height () - MARGIN, + Qt::KeepAspectRatio, Qt::SmoothTransformation)); + } }; -void AlbumArtQt::update (void * unused, QLabel * widget) -{ - if (! aud_drct_get_playing ()) - return; - - if (! widget) - return; +#undef MARGIN - QSize size = widget->size (); - widget->setPixmap (audqt::art_request_current (size.width (), size.height ())); +static void update (void *, ArtLabel * widget) +{ + widget->update_art (); } -void AlbumArtQt::clear (void * unused, QLabel * widget) +static void clear (void *, ArtLabel * widget) { - if (! widget) - return; - - widget->setPixmap (QPixmap ()); + widget->clear (); } -void AlbumArtQt::widget_cleanup (QObject * widget) +static void widget_cleanup (QObject * widget) { - hook_dissociate ("playback begin", (HookFunction) update, widget); - hook_dissociate ("current art ready", (HookFunction) update, widget); + hook_dissociate ("playback ready", (HookFunction) update, widget); hook_dissociate ("playback stop", (HookFunction) clear, widget); } void * AlbumArtQt::get_qt_widget () { - QLabel * widget = new QLabel; + ArtLabel * widget = new ArtLabel; QObject::connect (widget, &QObject::destroyed, widget_cleanup); - hook_associate ("playback begin", (HookFunction) update, widget); - hook_associate ("current art ready", (HookFunction) update, widget); + hook_associate ("playback ready", (HookFunction) update, widget); hook_associate ("playback stop", (HookFunction) clear, widget); - widget->resize (96, 96); - update (nullptr, widget); + if (aud_drct_get_ready ()) + widget->update_art (); return widget; } diff --git a/src/albumart/albumart.cc b/src/albumart/albumart.cc index 42de4c5..8711769 100644 --- a/src/albumart/albumart.cc +++ b/src/albumart/albumart.cc @@ -17,6 +17,7 @@ * the use of this software. */ +#define AUD_PLUGIN_GLIB_ONLY #include <libaudcore/drct.h> #include <libaudcore/i18n.h> #include <libaudcore/plugin.h> @@ -39,11 +40,8 @@ public: EXPORT AlbumArtPlugin aud_plugin_instance; -static void album_update (void * unused, GtkWidget * widget) +static void album_update (void *, GtkWidget * widget) { - if (! aud_drct_get_playing ()) - return; - GdkPixbuf * pixbuf = audgui_pixbuf_request_current (); if (! pixbuf) @@ -55,15 +53,14 @@ static void album_update (void * unused, GtkWidget * widget) g_object_unref (pixbuf); } -static void album_clear (void * unused, GtkWidget * widget) +static void album_clear (void *, GtkWidget * widget) { audgui_scaled_image_set (widget, nullptr); } static void album_cleanup (GtkWidget * widget) { - hook_dissociate ("playback begin", (HookFunction) album_update, widget); - hook_dissociate ("current art ready", (HookFunction) album_update, widget); + hook_dissociate ("playback ready", (HookFunction) album_update, widget); hook_dissociate ("playback stop", (HookFunction) album_clear, widget); audgui_cleanup (); @@ -74,15 +71,14 @@ void * AlbumArtPlugin::get_gtk_widget () audgui_init (); GtkWidget * widget = audgui_scaled_image_new (nullptr); - gtk_widget_set_size_request (widget, 96, 96); g_signal_connect (widget, "destroy", (GCallback) album_cleanup, nullptr); - hook_associate ("playback begin", (HookFunction) album_update, widget); - hook_associate ("current art ready", (HookFunction) album_update, widget); + hook_associate ("playback ready", (HookFunction) album_update, widget); hook_associate ("playback stop", (HookFunction) album_clear, widget); - album_update (nullptr, widget); + if (aud_drct_get_ready ()) + album_update (nullptr, widget); return widget; } diff --git a/src/amidi-plug/Makefile b/src/amidi-plug/Makefile index dac6d08..6657a67 100644 --- a/src/amidi-plug/Makefile +++ b/src/amidi-plug/Makefile @@ -15,5 +15,10 @@ plugindir := ${plugindir}/${INPUT_PLUGIN_DIR} LD = ${CXX} CFLAGS += ${PLUGIN_CFLAGS} -CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GTK_CFLAGS} ${FLUIDSYNTH_CFLAGS} -I../.. -LIBS += ${GTK_LIBS} ${FLUIDSYNTH_LIBS} -lm +CPPFLAGS += ${PLUGIN_CPPFLAGS} ${FLUIDSYNTH_CFLAGS} -I../.. +LIBS += ${FLUIDSYNTH_LIBS} -lm + +ifeq ($(USE_GTK),yes) +CPPFLAGS += ${GTK_CFLAGS} +LIBS += ${GTK_LIBS} +endif diff --git a/src/amidi-plug/amidi-plug.cc b/src/amidi-plug/amidi-plug.cc index fcb3b9d..edb6d54 100644 --- a/src/amidi-plug/amidi-plug.cc +++ b/src/amidi-plug/amidi-plug.cc @@ -56,8 +56,10 @@ public: Tuple read_tuple (const char * filename, VFSFile & file); bool play (const char * filename, VFSFile & file); +#ifdef USE_GTK bool file_info_box (const char * filename, VFSFile & file) { i_fileinfo_gui (filename, file); return true; } +#endif protected: bool m_backend_initialized = false; diff --git a/src/amidi-plug/backend-fluidsynth/b-fluidsynth.cc b/src/amidi-plug/backend-fluidsynth/b-fluidsynth.cc index 098b13e..09d8c24 100644 --- a/src/amidi-plug/backend-fluidsynth/b-fluidsynth.cc +++ b/src/amidi-plug/backend-fluidsynth/b-fluidsynth.cc @@ -45,9 +45,9 @@ sequencer_client_t; static sequencer_client_t sc; /* options */ -static void i_soundfont_load (void); +static void i_soundfont_load (); -void backend_init (void) +void backend_init () { sc.settings = new_fluid_settings(); @@ -82,7 +82,7 @@ void backend_init (void) } -void backend_cleanup (void) +void backend_cleanup () { /* unload soundfonts */ for (int id : sc.soundfont_ids) @@ -94,7 +94,7 @@ void backend_cleanup (void) } -void backend_reset (void) +void backend_reset () { fluid_synth_system_reset (sc.synth); /* all notes off and channels reset */ } @@ -204,7 +204,7 @@ void backend_audio_info (int * channels, int * bitdepth, int * samplerate) *** INTERNALS **************************************************** ****************************************************************** */ -static void i_soundfont_load (void) +static void i_soundfont_load () { String soundfont_file = aud_get_str ("amidiplug", "fsyn_soundfont_file"); diff --git a/src/amidi-plug/i_backend.h b/src/amidi-plug/i_backend.h index 54aecfb..d4f9ce3 100644 --- a/src/amidi-plug/i_backend.h +++ b/src/amidi-plug/i_backend.h @@ -23,9 +23,9 @@ struct midievent_t; -void backend_init (void); -void backend_cleanup (void); -void backend_reset (void); +void backend_init (); +void backend_cleanup (); +void backend_reset (); void backend_audio_info (int *, int *, int *); void backend_generate_audio (void * buf, int bufsize); diff --git a/src/amidi-plug/i_configure-fluidsynth.cc b/src/amidi-plug/i_configure-fluidsynth.cc index 7506701..0e460e2 100644 --- a/src/amidi-plug/i_configure-fluidsynth.cc +++ b/src/amidi-plug/i_configure-fluidsynth.cc @@ -20,6 +20,8 @@ #include "i_configure-fluidsynth.h" +#ifdef USE_GTK + #include <stdlib.h> #include <string.h> #include <sys/stat.h> @@ -147,9 +149,9 @@ void i_configure_ev_sflist_commit (void * sfont_lv) GtkTreeModel * store = gtk_tree_view_get_model (GTK_TREE_VIEW (sfont_lv)); GString * sflist_string = g_string_new (""); - if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter) == TRUE) + if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (store), &iter) == true) { - gboolean iter_is_valid = FALSE; + gboolean iter_is_valid = false; do { @@ -161,7 +163,7 @@ void i_configure_ev_sflist_commit (void * sfont_lv) g_free (fname); iter_is_valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (store), &iter); } - while (iter_is_valid == TRUE); + while (iter_is_valid == true); } if (sflist_string->len > 0) @@ -169,14 +171,14 @@ void i_configure_ev_sflist_commit (void * sfont_lv) aud_set_str ("amidiplug", "fsyn_soundfont_file", sflist_string->str); - g_string_free (sflist_string, TRUE); + g_string_free (sflist_string, true); /* reset backend at beginning of next song to apply changes */ __sync_bool_compare_and_swap (& backend_settings_changed, false, true); } -void * create_soundfont_list (void) +void * create_soundfont_list () { GtkListStore * soundfont_file_store; GtkCellRenderer * soundfont_file_lv_text_rndr; @@ -216,19 +218,19 @@ void * create_soundfont_list (void) g_strfreev (sffiles); } - soundfont_file_hbox = gtk_hbox_new (FALSE, 2); + soundfont_file_hbox = gtk_hbox_new (false, 2); soundfont_file_lv = gtk_tree_view_new_with_model (GTK_TREE_MODEL (soundfont_file_store)); - gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (soundfont_file_lv), TRUE); + gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (soundfont_file_lv), true); g_object_unref (soundfont_file_store); soundfont_file_lv_text_rndr = gtk_cell_renderer_text_new(); soundfont_file_lv_fname_col = gtk_tree_view_column_new_with_attributes ( _("File name"), soundfont_file_lv_text_rndr, "text", LISTSFONT_FILENAME_COLUMN, nullptr); - gtk_tree_view_column_set_expand (GTK_TREE_VIEW_COLUMN (soundfont_file_lv_fname_col), TRUE); + gtk_tree_view_column_set_expand (GTK_TREE_VIEW_COLUMN (soundfont_file_lv_fname_col), true); soundfont_file_lv_fsize_col = gtk_tree_view_column_new_with_attributes ( _("Size (bytes)"), soundfont_file_lv_text_rndr, "text", LISTSFONT_FILESIZE_COLUMN, nullptr); - gtk_tree_view_column_set_expand (GTK_TREE_VIEW_COLUMN (soundfont_file_lv_fsize_col), FALSE); + gtk_tree_view_column_set_expand (GTK_TREE_VIEW_COLUMN (soundfont_file_lv_fsize_col), false); gtk_tree_view_append_column (GTK_TREE_VIEW (soundfont_file_lv), soundfont_file_lv_fname_col); gtk_tree_view_append_column (GTK_TREE_VIEW (soundfont_file_lv), soundfont_file_lv_fsize_col); soundfont_file_lv_sel = gtk_tree_view_get_selection (GTK_TREE_VIEW (soundfont_file_lv)); @@ -241,35 +243,37 @@ void * create_soundfont_list (void) gtk_container_add (GTK_CONTAINER (soundfont_file_lv_sw), soundfont_file_lv); /* soundfont settings - soundfont files - buttonbox */ - soundfont_file_bbox_vbox = gtk_vbox_new (FALSE, 0); + soundfont_file_bbox_vbox = gtk_vbox_new (false, 0); soundfont_file_bbox_addbt = gtk_button_new(); gtk_button_set_image (GTK_BUTTON (soundfont_file_bbox_addbt), gtk_image_new_from_icon_name ("list-add", GTK_ICON_SIZE_MENU)); g_signal_connect_swapped (G_OBJECT (soundfont_file_bbox_addbt), "clicked", G_CALLBACK (i_configure_ev_sflist_add), soundfont_file_lv); - gtk_box_pack_start (GTK_BOX (soundfont_file_bbox_vbox), soundfont_file_bbox_addbt, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (soundfont_file_bbox_vbox), soundfont_file_bbox_addbt, false, false, 0); soundfont_file_bbox_rembt = gtk_button_new(); gtk_button_set_image (GTK_BUTTON (soundfont_file_bbox_rembt), gtk_image_new_from_icon_name ("list-remove", GTK_ICON_SIZE_MENU)); g_signal_connect_swapped (G_OBJECT (soundfont_file_bbox_rembt), "clicked", G_CALLBACK (i_configure_ev_sflist_rem), soundfont_file_lv); - gtk_box_pack_start (GTK_BOX (soundfont_file_bbox_vbox), soundfont_file_bbox_rembt, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (soundfont_file_bbox_vbox), soundfont_file_bbox_rembt, false, false, 0); soundfont_file_bbox_mvupbt = gtk_button_new(); gtk_button_set_image (GTK_BUTTON (soundfont_file_bbox_mvupbt), gtk_image_new_from_icon_name ("go-up", GTK_ICON_SIZE_MENU)); g_object_set_data (G_OBJECT (soundfont_file_bbox_mvupbt), "swapdire", GUINT_TO_POINTER (0)); g_signal_connect (G_OBJECT (soundfont_file_bbox_mvupbt), "clicked", G_CALLBACK (i_configure_ev_sflist_swap), soundfont_file_lv); - gtk_box_pack_start (GTK_BOX (soundfont_file_bbox_vbox), soundfont_file_bbox_mvupbt, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (soundfont_file_bbox_vbox), soundfont_file_bbox_mvupbt, false, false, 0); soundfont_file_bbox_mvdownbt = gtk_button_new(); gtk_button_set_image (GTK_BUTTON (soundfont_file_bbox_mvdownbt), gtk_image_new_from_icon_name ("go-down", GTK_ICON_SIZE_MENU)); g_object_set_data (G_OBJECT (soundfont_file_bbox_mvdownbt), "swapdire", GUINT_TO_POINTER (1)); g_signal_connect (G_OBJECT (soundfont_file_bbox_mvdownbt), "clicked", G_CALLBACK (i_configure_ev_sflist_swap), soundfont_file_lv); - gtk_box_pack_start (GTK_BOX (soundfont_file_bbox_vbox), soundfont_file_bbox_mvdownbt, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX (soundfont_file_hbox), soundfont_file_lv_sw, TRUE, TRUE, 0); - gtk_box_pack_start (GTK_BOX (soundfont_file_hbox), soundfont_file_bbox_vbox, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (soundfont_file_bbox_vbox), soundfont_file_bbox_mvdownbt, false, false, 0); + gtk_box_pack_start (GTK_BOX (soundfont_file_hbox), soundfont_file_lv_sw, true, true, 0); + gtk_box_pack_start (GTK_BOX (soundfont_file_hbox), soundfont_file_bbox_vbox, false, false, 0); return soundfont_file_hbox; } + +#endif // USE_GTK diff --git a/src/amidi-plug/i_configure-fluidsynth.h b/src/amidi-plug/i_configure-fluidsynth.h index dda878b..f6af4d8 100644 --- a/src/amidi-plug/i_configure-fluidsynth.h +++ b/src/amidi-plug/i_configure-fluidsynth.h @@ -21,6 +21,6 @@ #ifndef _I_CONFIGURE_FLUIDSYNTH_H #define _I_CONFIGURE_FLUIDSYNTH_H 1 -void * create_soundfont_list (void); +void * create_soundfont_list (); #endif /* !_I_CONFIGURE_FLUIDSYNTH_H */ diff --git a/src/amidi-plug/i_configure.cc b/src/amidi-plug/i_configure.cc index f192d2b..6d551e5 100644 --- a/src/amidi-plug/i_configure.cc +++ b/src/amidi-plug/i_configure.cc @@ -37,7 +37,7 @@ static bool reverb_setting = true; static bool override_chorus = false; static bool chorus_setting = true; -static void get_values (void) +static void get_values () { int gain = aud_get_int ("amidiplug", "fsyn_synth_gain"); int polyphony = aud_get_int ("amidiplug", "fsyn_synth_polyphony"); @@ -69,7 +69,7 @@ static void get_values (void) } } -static void set_values (void) +static void set_values () { int gain = override_gain ? (int) (gain_setting * 10 + 0.5) : -1; int polyphony = override_polyphony ? polyphony_setting : -1; @@ -82,7 +82,7 @@ static void set_values (void) aud_set_int ("amidiplug", "fsyn_synth_chorus", chorus); } -static void backend_change (void) +static void backend_change () { set_values (); @@ -139,7 +139,9 @@ static const PreferencesWidget amidiplug_widgets[] = { /* backend settings */ WidgetLabel (N_("<b>SoundFont</b>")), +#ifdef USE_GTK WidgetCustomGTK (create_soundfont_list), +#endif WidgetLabel (N_("<b>Synthesizer</b>")), WidgetBox ({{gain_widgets}, true}), WidgetBox ({{polyphony_widgets}, true}), diff --git a/src/amidi-plug/i_fileinfo.cc b/src/amidi-plug/i_fileinfo.cc index fc04c4c..1a2ee7e 100644 --- a/src/amidi-plug/i_fileinfo.cc +++ b/src/amidi-plug/i_fileinfo.cc @@ -20,6 +20,8 @@ #include "i_fileinfo.h" +#ifdef USE_GTK + #include <limits.h> #include <stdlib.h> #include <string.h> @@ -139,7 +141,7 @@ void i_fileinfo_gui (const char * filename_uri, VFSFile & file) g_signal_connect (G_OBJECT (fileinfowin), "destroy", G_CALLBACK (gtk_widget_destroyed), &fileinfowin); gtk_container_set_border_width (GTK_CONTAINER (fileinfowin), 10); - fileinfowin_vbox = gtk_vbox_new (FALSE, 10); + fileinfowin_vbox = gtk_vbox_new (false, 10); gtk_container_add (GTK_CONTAINER (fileinfowin), fileinfowin_vbox); /* pango attributes */ @@ -151,39 +153,39 @@ void i_fileinfo_gui (const char * filename_uri, VFSFile & file) /****************** *** TITLE LINE ***/ - title_hbox = gtk_hbox_new (FALSE, 5); - gtk_box_pack_start (GTK_BOX (fileinfowin_vbox), title_hbox, FALSE, FALSE, 0); + title_hbox = gtk_hbox_new (false, 5); + gtk_box_pack_start (GTK_BOX (fileinfowin_vbox), title_hbox, false, false, 0); title_icon_pixbuf = gdk_pixbuf_new_from_xpm_data ((const char **) amidiplug_xpm_midiicon); title_icon_image = gtk_image_new_from_pixbuf (title_icon_pixbuf); g_object_unref (title_icon_pixbuf); gtk_misc_set_alignment (GTK_MISC (title_icon_image), 0, 0); - gtk_box_pack_start (GTK_BOX (title_hbox), title_icon_image, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (title_hbox), title_icon_image, false, false, 0); title_name_f_label = gtk_label_new (_("Name:")); gtk_label_set_attributes (GTK_LABEL (title_name_f_label), pangoattrlist); - gtk_box_pack_start (GTK_BOX (title_hbox), title_name_f_label, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (title_hbox), title_name_f_label, false, false, 0); title_name_v_entry = gtk_entry_new(); - gtk_editable_set_editable (GTK_EDITABLE (title_name_v_entry), FALSE); + gtk_editable_set_editable (GTK_EDITABLE (title_name_v_entry), false); gtk_widget_set_size_request (GTK_WIDGET (title_name_v_entry), 200, -1); - gtk_box_pack_start (GTK_BOX (title_hbox), title_name_v_entry, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (title_hbox), title_name_v_entry, true, true, 0); - fileinfowin_columns_hbox = gtk_hbox_new (FALSE, 2); - gtk_box_pack_start (GTK_BOX (fileinfowin_vbox), fileinfowin_columns_hbox, TRUE, TRUE, 0); + fileinfowin_columns_hbox = gtk_hbox_new (false, 2); + gtk_box_pack_start (GTK_BOX (fileinfowin_vbox), fileinfowin_columns_hbox, true, true, 0); /********************* *** MIDI INFO BOX ***/ - midiinfoboxes_vbox = gtk_vbox_new (FALSE, 2); - gtk_box_pack_start (GTK_BOX (fileinfowin_columns_hbox), midiinfoboxes_vbox, FALSE, FALSE, 0); + midiinfoboxes_vbox = gtk_vbox_new (false, 2); + gtk_box_pack_start (GTK_BOX (fileinfowin_columns_hbox), midiinfoboxes_vbox, false, false, 0); info_frame_tl = gtk_label_new (""); gtk_label_set_markup (GTK_LABEL (info_frame_tl), _("<span size=\"smaller\"> MIDI Info </span>")); - gtk_box_pack_start (GTK_BOX (midiinfoboxes_vbox), info_frame_tl, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (midiinfoboxes_vbox), info_frame_tl, false, false, 0); info_frame = gtk_frame_new (nullptr); - gtk_box_pack_start (GTK_BOX (midiinfoboxes_vbox), info_frame, TRUE, TRUE, 0); - info_grid = gtk_table_new (0, 0, FALSE); + gtk_box_pack_start (GTK_BOX (midiinfoboxes_vbox), info_frame, true, true, 0); + info_grid = gtk_table_new (0, 0, false); gtk_table_set_row_spacings (GTK_TABLE (info_grid), 2); gtk_table_set_col_spacings (GTK_TABLE (info_grid), 6); gtk_container_set_border_width (GTK_CONTAINER (info_grid), 6); @@ -219,26 +221,26 @@ void i_fileinfo_gui (const char * filename_uri, VFSFile & file) g_string_printf (value_gstring, "%i", mf.time_division); i_fileinfo_grid_add_entry (_("Time Div:"), value_gstring->str, info_grid, 5, pangoattrlist); - g_string_free (value_gstring, TRUE); + g_string_free (value_gstring, true); /********************************** *** MIDI COMMENTS/LYRICS BOXES ***/ - miditextboxes_vbox = gtk_vbox_new (FALSE, 2); - gtk_box_pack_start (GTK_BOX (fileinfowin_columns_hbox), miditextboxes_vbox, TRUE, TRUE, 0); + miditextboxes_vbox = gtk_vbox_new (false, 2); + gtk_box_pack_start (GTK_BOX (fileinfowin_columns_hbox), miditextboxes_vbox, true, true, 0); text_frame_tl = gtk_label_new (""); gtk_label_set_markup (GTK_LABEL (text_frame_tl), _("<span size=\"smaller\"> MIDI Comments and Lyrics </span>")); - gtk_box_pack_start (GTK_BOX (miditextboxes_vbox), text_frame_tl, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (miditextboxes_vbox), text_frame_tl, false, false, 0); miditextboxes_paned = gtk_vpaned_new (); - gtk_box_pack_start (GTK_BOX (miditextboxes_vbox), miditextboxes_paned, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (miditextboxes_vbox), miditextboxes_paned, true, true, 0); text_frame = gtk_frame_new (nullptr); - gtk_paned_pack1 (GTK_PANED (miditextboxes_paned), text_frame, TRUE, TRUE); + gtk_paned_pack1 (GTK_PANED (miditextboxes_paned), text_frame, true, true); text_tv = gtk_text_view_new(); - gtk_text_view_set_editable (GTK_TEXT_VIEW (text_tv), FALSE); - gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (text_tv), FALSE); + gtk_text_view_set_editable (GTK_TEXT_VIEW (text_tv), false); + gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (text_tv), false); gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (text_tv), GTK_WRAP_WORD); gtk_text_view_set_right_margin (GTK_TEXT_VIEW (text_tv), 4); gtk_text_view_set_left_margin (GTK_TEXT_VIEW (text_tv), 4); @@ -250,10 +252,10 @@ void i_fileinfo_gui (const char * filename_uri, VFSFile & file) gtk_container_add (GTK_CONTAINER (text_tv_sw), text_tv); lyrics_frame = gtk_frame_new (nullptr); - gtk_paned_pack2 (GTK_PANED (miditextboxes_paned), lyrics_frame, TRUE, TRUE); + gtk_paned_pack2 (GTK_PANED (miditextboxes_paned), lyrics_frame, true, true); lyrics_tv = gtk_text_view_new(); - gtk_text_view_set_editable (GTK_TEXT_VIEW (lyrics_tv), FALSE); - gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (lyrics_tv), FALSE); + gtk_text_view_set_editable (GTK_TEXT_VIEW (lyrics_tv), false); + gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (lyrics_tv), false); gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (lyrics_tv), GTK_WRAP_WORD); gtk_text_view_set_right_margin (GTK_TEXT_VIEW (lyrics_tv), 4); gtk_text_view_set_left_margin (GTK_TEXT_VIEW (lyrics_tv), 4); @@ -300,7 +302,7 @@ void i_fileinfo_gui (const char * filename_uri, VFSFile & file) footer_bclose = gtk_button_new_with_mnemonic (_("_Close")); g_signal_connect (G_OBJECT (footer_bclose), "clicked", G_CALLBACK (i_fileinfo_ev_close), fileinfowin); gtk_container_add (GTK_CONTAINER (footer_hbbox), footer_bclose); - gtk_box_pack_start (GTK_BOX (fileinfowin_vbox), footer_hbbox, FALSE, FALSE, 0); + gtk_box_pack_start (GTK_BOX (fileinfowin_vbox), footer_hbbox, false, false, 0); /* utf8-ize filename and set window title */ @@ -338,3 +340,5 @@ void i_fileinfo_gui (const char * filename_uri, VFSFile & file) gtk_widget_grab_focus (GTK_WIDGET (footer_bclose)); gtk_widget_show_all (fileinfowin); } + +#endif // USE_GTK diff --git a/src/aosd/aosd.cc b/src/aosd/aosd.cc index db49b1f..e3b1a11 100644 --- a/src/aosd/aosd.cc +++ b/src/aosd/aosd.cc @@ -19,7 +19,6 @@ */ #include <libaudcore/i18n.h> -#include <libaudcore/plugin.h> #include "aosd.h" #include "aosd_osd.h" diff --git a/src/aosd/aosd.h b/src/aosd/aosd.h index f7de153..0d7cb8e 100644 --- a/src/aosd/aosd.h +++ b/src/aosd/aosd.h @@ -21,6 +21,7 @@ #ifndef _I_AOSD_H #define _I_AOSD_H 1 +#define AUD_PLUGIN_GLIB_ONLY #include <libaudcore/plugin.h> struct PreferencesWidget; diff --git a/src/aosd/aosd_cfg.cc b/src/aosd/aosd_cfg.cc index c0e242b..2c7ae57 100644 --- a/src/aosd/aosd_cfg.cc +++ b/src/aosd/aosd_cfg.cc @@ -27,7 +27,6 @@ #include <libaudcore/audstrings.h> #include <libaudcore/runtime.h> -#include <libaudcore/plugin.h> static aosd_color_t str_to_color (const char * str) { @@ -46,7 +45,7 @@ static StringBuf color_to_str (const aosd_color_t & color) } static const char * const aosd_defaults[] = { - "position_placement", "1", /* AOSD_POSITION_PLACEMENT_TOPLEFT */ + "position_placement", aud::numeric_string<AOSD_POSITION_PLACEMENT_TOPLEFT>::str, "position_offset_x", "0", "position_offset_y", "0", "position_maxsize_width", "0", diff --git a/src/aosd/aosd_osd.cc b/src/aosd/aosd_osd.cc index 88eea06..d76c561 100644 --- a/src/aosd/aosd_osd.cc +++ b/src/aosd/aosd_osd.cc @@ -194,7 +194,7 @@ aosd_osd_create ( void ) osd_data->pango_layout = pango_layout_new(osd_data->pango_context); pango_layout_set_markup( osd_data->pango_layout, osd_data->markup_message , -1 ); pango_layout_set_ellipsize( osd_data->pango_layout , PANGO_ELLIPSIZE_NONE ); - pango_layout_set_justify( osd_data->pango_layout , FALSE ); + pango_layout_set_justify( osd_data->pango_layout , false ); pango_layout_set_width( osd_data->pango_layout , PANGO_SCALE * max_width ); pango_layout_get_pixel_extents( osd_data->pango_layout , &ink , &log ); layout_width = ink.width; @@ -296,7 +296,7 @@ aosd_timer_func ( void * none ) ghosd_render( osd ); ghosd_main_iterations( osd ); } - return TRUE; + return true; } case AOSD_STATUS_SHOW: @@ -311,7 +311,7 @@ aosd_timer_func ( void * none ) { ghosd_main_iterations( osd ); } - return TRUE; + return true; } case AOSD_STATUS_FADEOUT: @@ -330,7 +330,7 @@ aosd_timer_func ( void * none ) ghosd_render( osd ); ghosd_main_iterations( osd ); } - return TRUE; + return true; } case AOSD_STATUS_DESTROY: @@ -340,11 +340,11 @@ aosd_timer_func ( void * none ) osd_status = AOSD_STATUS_HIDDEN; /* reset status */ osd_source_id = 0; - return FALSE; + return false; } } - return TRUE; + return true; } @@ -482,7 +482,7 @@ aosd_osd_check_composite_mgr ( void ) int exit_status; if ( g_spawn_command_line_sync( "ps -eo comm" , - &soutput , &serror , &exit_status , nullptr ) == TRUE ) + &soutput , &serror , &exit_status , nullptr ) == true ) { if (( soutput != nullptr ) && ( strstr( soutput , "\nxcompmgr\n" ) != nullptr )) { diff --git a/src/aosd/aosd_style.cc b/src/aosd/aosd_style.cc index 9cd855b..9194ac2 100644 --- a/src/aosd/aosd_style.cc +++ b/src/aosd/aosd_style.cc @@ -161,7 +161,7 @@ aosd_deco_rfunc_rect( Ghosd * osd , cairo_t * cr , aosd_deco_style_data_t * data (double)color1.blue / 65535 , (double)color1.alpha / 65535 ); cairo_stroke( cr ); - if ( draw_shadow == TRUE ) + if ( draw_shadow == true ) { /* draw text shadow */ cairo_set_source_rgba( cr , (double)shadowcolor0.red / 65535 , (double)shadowcolor0.green / 65535 , @@ -222,7 +222,7 @@ aosd_deco_rfunc_roundrect ( Ghosd * osd , cairo_t * cr , aosd_deco_style_data_t (double)color1.blue / 65535 , (double)color1.alpha / 65535 ); cairo_stroke( cr ); - if ( draw_shadow == TRUE ) + if ( draw_shadow == true ) { /* draw text shadow */ cairo_set_source_rgba( cr , (double)shadowcolor0.red / 65535 , (double)shadowcolor0.green / 65535 , @@ -283,7 +283,7 @@ aosd_deco_rfunc_concaverect ( Ghosd * osd , cairo_t * cr , aosd_deco_style_data_ (double)color1.blue / 65535 , (double)color1.alpha / 65535 ); cairo_stroke( cr ); - if ( draw_shadow == TRUE ) + if ( draw_shadow == true ) { /* draw text shadow */ cairo_set_source_rgba( cr , (double)shadowcolor0.red / 65535 , (double)shadowcolor0.green / 65535 , @@ -320,7 +320,7 @@ aosd_deco_rfunc_none ( Ghosd * osd , cairo_t * cr , aosd_deco_style_data_t * dat aosd_layout_size( osd_layout , &width , &height , &bearing ); - if ( draw_shadow == TRUE ) + if ( draw_shadow == true ) { /* draw text shadow */ cairo_set_source_rgba( cr , (double)shadowcolor0.red / 65535 , (double)shadowcolor0.green / 65535 , diff --git a/src/aosd/aosd_trigger.cc b/src/aosd/aosd_trigger.cc index e9f3ee7..a5416b5 100644 --- a/src/aosd/aosd_trigger.cc +++ b/src/aosd/aosd_trigger.cc @@ -23,7 +23,6 @@ #include <libaudcore/drct.h> #include <libaudcore/i18n.h> -#include <libaudcore/plugin.h> #include <libaudcore/audstrings.h> #include <libaudcore/hook.h> @@ -124,7 +123,7 @@ void aosd_trigger_stop (const aosd_cfg_osd_trigger_t & cfg_trigger) static void aosd_trigger_func_pb_start_onoff ( bool turn_on ) { - if (turn_on == TRUE) + if (turn_on == true) hook_associate("playback ready", aosd_trigger_func_pb_start_cb, nullptr); else hook_dissociate("playback ready", aosd_trigger_func_pb_start_cb); @@ -137,7 +136,7 @@ aosd_trigger_func_pb_start_cb(void * hook_data, void * user_data) char * markup = g_markup_printf_escaped ("<span font_desc='%s'>%s</span>", (const char *) global_config.text.fonts_name[0], (const char *) title); - aosd_osd_display (markup, & global_config, FALSE); + aosd_osd_display (markup, & global_config, false); g_free (markup); } @@ -153,7 +152,7 @@ aosd_trigger_func_pb_titlechange_onoff ( bool turn_on ) { static aosd_pb_titlechange_prevs_t *prevs = nullptr; - if ( turn_on == TRUE ) + if ( turn_on == true ) { prevs = new aosd_pb_titlechange_prevs_t; hook_associate( "title change" , aosd_trigger_func_pb_titlechange_cb , prevs ); @@ -193,7 +192,7 @@ aosd_trigger_func_pb_titlechange_cb ( void * plentry_gp , void * prevs_gp ) (const char *) global_config.text.fonts_name[0], (const char *) pl_entry_title); - aosd_osd_display (markup, & global_config, FALSE); + aosd_osd_display (markup, & global_config, false); g_free (markup); prevs->title = pl_entry_title; @@ -217,7 +216,7 @@ aosd_trigger_func_pb_titlechange_cb ( void * plentry_gp , void * prevs_gp ) static void aosd_trigger_func_pb_pauseon_onoff ( bool turn_on ) { - if ( turn_on == TRUE ) + if ( turn_on == true ) hook_associate( "playback pause" , aosd_trigger_func_pb_pauseon_cb , nullptr ); else hook_dissociate( "playback pause" , aosd_trigger_func_pb_pauseon_cb ); @@ -228,7 +227,7 @@ aosd_trigger_func_pb_pauseon_cb ( void * unused1 , void * unused2 ) { char * markup = g_markup_printf_escaped ("<span font_desc='%s'>Paused</span>", (const char *) global_config.text.fonts_name[0]); - aosd_osd_display (markup, & global_config, FALSE); + aosd_osd_display (markup, & global_config, false); g_free (markup); } @@ -236,7 +235,7 @@ aosd_trigger_func_pb_pauseon_cb ( void * unused1 , void * unused2 ) static void aosd_trigger_func_pb_pauseoff_onoff ( bool turn_on ) { - if ( turn_on == TRUE ) + if ( turn_on == true ) hook_associate( "playback unpause" , aosd_trigger_func_pb_pauseoff_cb , nullptr ); else hook_dissociate( "playback unpause" , aosd_trigger_func_pb_pauseoff_cb ); @@ -262,7 +261,7 @@ aosd_trigger_func_pb_pauseoff_cb ( void * unused1 , void * unused2 ) (const char *) global_config.text.fonts_name[0], (const char *) title, time_cur_m, time_cur_s, time_tot_m, time_tot_s); - aosd_osd_display (markup, & global_config, FALSE); + aosd_osd_display (markup, & global_config, false); g_free (markup); } @@ -276,7 +275,7 @@ aosd_trigger_func_hook_cb ( void * markup_text , void * unused ) if ( markup_text != nullptr ) { /* Display text from caller */ - aosd_osd_display ((char *) markup_text, & global_config, FALSE); + aosd_osd_display ((char *) markup_text, & global_config, false); } else { /* Display currently playing song */ aosd_trigger_func_pb_start_cb (nullptr, nullptr); diff --git a/src/aosd/aosd_ui.cc b/src/aosd/aosd_ui.cc index 306d522..3f3862e 100644 --- a/src/aosd/aosd_ui.cc +++ b/src/aosd/aosd_ui.cc @@ -50,7 +50,7 @@ static void chooser_set_aosd_color (GtkColorButton * chooser, const aosd_color_t GdkColor gdk_color = {0, (uint16_t) color->red, (uint16_t) color->green, (uint16_t) color->blue}; gtk_color_button_set_color (chooser, & gdk_color); - gtk_color_button_set_use_alpha (chooser, TRUE); + gtk_color_button_set_use_alpha (chooser, true); gtk_color_button_set_alpha (chooser, color->alpha); } @@ -91,7 +91,7 @@ aosd_cb_configure_position_expose ( GtkWidget * darea , cairo_fill ( cr ); cairo_destroy (cr); - return FALSE; + return false; } @@ -104,7 +104,7 @@ aosd_cb_configure_position_placement_commit ( GtkWidget * grid , aosd_cfg_t * cf while ( list_iter != nullptr ) { GtkWidget *placbt = (GtkWidget *) list_iter->data; - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(placbt) ) == TRUE ) + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(placbt) ) == true ) { cfg->position.placement = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(placbt),"value")); break; @@ -157,23 +157,23 @@ aosd_ui_configure_position ( aosd_cfg_t * cfg ) int monitors_num = gdk_screen_get_n_monitors( gdk_screen_get_default() ); int i = 0; - pos_vbox = gtk_vbox_new( FALSE , 4 ); + pos_vbox = gtk_vbox_new( false , 4 ); gtk_container_set_border_width( GTK_CONTAINER(pos_vbox) , 6 ); pos_placement_frame = gtk_frame_new( _("Placement") ); - pos_placement_hbox = gtk_hbox_new( FALSE , 0 ); + pos_placement_hbox = gtk_hbox_new( false , 0 ); gtk_container_set_border_width( GTK_CONTAINER(pos_placement_hbox) , 6 ); gtk_container_add( GTK_CONTAINER(pos_placement_frame) , pos_placement_hbox ); - gtk_box_pack_start( GTK_BOX(pos_vbox) , pos_placement_frame , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(pos_vbox) , pos_placement_frame , false , false , 0 ); - pos_placement_grid = gtk_table_new (0, 0, FALSE); + pos_placement_grid = gtk_table_new (0, 0, false); for ( i = 0 ; i < 9 ; i++ ) { if ( i == 0 ) pos_placement_bt[i] = gtk_radio_button_new( nullptr ); else pos_placement_bt[i] = gtk_radio_button_new_from_widget( GTK_RADIO_BUTTON(pos_placement_bt[0]) ); - gtk_toggle_button_set_mode( GTK_TOGGLE_BUTTON(pos_placement_bt[i]) , FALSE ); + gtk_toggle_button_set_mode( GTK_TOGGLE_BUTTON(pos_placement_bt[i]) , false ); pos_placement_bt_darea[i] = gtk_drawing_area_new(); gtk_widget_set_size_request( pos_placement_bt_darea[i] , 40 , 40 ); gtk_container_add( GTK_CONTAINER(pos_placement_bt[i]) , pos_placement_bt_darea[i] ); @@ -183,14 +183,14 @@ aosd_ui_configure_position ( aosd_cfg_t * cfg ) (i % 3) , (i % 3) + 1 , (i / 3) , (i / 3) + 1 ); g_object_set_data( G_OBJECT(pos_placement_bt[i]) , "value" , GINT_TO_POINTER(i+1) ); if ( cfg->position.placement == (i+1) ) - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(pos_placement_bt[i]) , TRUE ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(pos_placement_bt[i]) , true ); } - gtk_box_pack_start( GTK_BOX(pos_placement_hbox) , pos_placement_grid , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(pos_placement_hbox) , pos_placement_grid , false , false , 0 ); aosd_cb_list.append( pos_placement_grid , aosd_cb_configure_position_placement_commit ); - gtk_box_pack_start( GTK_BOX(pos_placement_hbox) , gtk_vseparator_new() , FALSE , FALSE , 6 ); + gtk_box_pack_start( GTK_BOX(pos_placement_hbox) , gtk_vseparator_new() , false , false , 6 ); - pos_offset_grid = gtk_table_new (0, 0, FALSE); + pos_offset_grid = gtk_table_new (0, 0, false); gtk_table_set_row_spacings( GTK_TABLE(pos_offset_grid) , 4 ); gtk_table_set_col_spacings( GTK_TABLE(pos_offset_grid) , 4 ); pos_offset_x_label = gtk_label_new( _( "Relative X offset:" ) ); @@ -214,12 +214,12 @@ aosd_ui_configure_position ( aosd_cfg_t * cfg ) g_object_set_data( G_OBJECT(pos_offset_grid) , "maxsize_width" , pos_maxsize_width_spinbt ); gtk_spin_button_set_value( GTK_SPIN_BUTTON(pos_maxsize_width_spinbt) , cfg->position.maxsize_width ); gtk_table_attach_defaults( GTK_TABLE(pos_offset_grid) , pos_maxsize_width_spinbt , 1 , 2 , 2 , 3 ); - gtk_box_pack_start( GTK_BOX(pos_placement_hbox) , pos_offset_grid , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(pos_placement_hbox) , pos_offset_grid , false , false , 0 ); aosd_cb_list.append( pos_offset_grid , aosd_cb_configure_position_offset_commit ); aosd_cb_list.append( pos_offset_grid , aosd_cb_configure_position_maxsize_commit ); pos_multimon_frame = gtk_frame_new( _("Multi-Monitor options") ); - pos_multimon_hbox = gtk_hbox_new( FALSE , 4 ); + pos_multimon_hbox = gtk_hbox_new( false , 4 ); gtk_container_set_border_width( GTK_CONTAINER(pos_multimon_hbox) , 6 ); gtk_container_add( GTK_CONTAINER(pos_multimon_frame), pos_multimon_hbox ); pos_multimon_label = gtk_label_new( _("Display OSD using:") ); @@ -233,9 +233,9 @@ aosd_ui_configure_position ( aosd_cfg_t * cfg ) } gtk_combo_box_set_active( GTK_COMBO_BOX(pos_multimon_combobox) , (cfg->position.multimon_id + 1) ); aosd_cb_list.append( pos_multimon_combobox , aosd_cb_configure_position_multimon_commit ); - gtk_box_pack_start( GTK_BOX(pos_multimon_hbox) , pos_multimon_label , FALSE , FALSE , 0 ); - gtk_box_pack_start( GTK_BOX(pos_multimon_hbox) , pos_multimon_combobox , FALSE , FALSE , 0 ); - gtk_box_pack_start( GTK_BOX(pos_vbox) , pos_multimon_frame , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(pos_multimon_hbox) , pos_multimon_label , false , false , 0 ); + gtk_box_pack_start( GTK_BOX(pos_multimon_hbox) , pos_multimon_combobox , false , false , 0 ); + gtk_box_pack_start( GTK_BOX(pos_vbox) , pos_multimon_frame , false , false , 0 ); return pos_vbox; } @@ -245,11 +245,11 @@ static GtkWidget * aosd_ui_configure_animation_timing ( char * label_string ) { GtkWidget *hbox, *desc_label, *spinbt; - hbox = gtk_hbox_new( FALSE , 4 ); + hbox = gtk_hbox_new( false , 4 ); desc_label = gtk_label_new( label_string ); spinbt = gtk_spin_button_new_with_range( 0 , 99999 , 1 ); - gtk_box_pack_start( GTK_BOX(hbox) , desc_label , FALSE , FALSE , 0 ); - gtk_box_pack_start( GTK_BOX(hbox) , spinbt , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(hbox) , desc_label , false , false , 0 ); + gtk_box_pack_start( GTK_BOX(hbox) , spinbt , false , false , 0 ); g_object_set_data( G_OBJECT(hbox) , "spinbt" , spinbt ); return hbox; } @@ -275,29 +275,29 @@ aosd_ui_configure_animation ( aosd_cfg_t * cfg ) GtkWidget *ani_timing_fadein_widget, *ani_timing_fadeout_widget, *ani_timing_stay_widget; GtkSizeGroup *sizegroup; - ani_vbox = gtk_vbox_new( FALSE , 0 ); + ani_vbox = gtk_vbox_new( false , 0 ); gtk_container_set_border_width( GTK_CONTAINER(ani_vbox) , 6 ); - ani_timing_hbox = gtk_hbox_new( FALSE , 0 ); + ani_timing_hbox = gtk_hbox_new( false , 0 ); ani_timing_frame = gtk_frame_new( _("Timing (ms)") ); gtk_container_set_border_width( GTK_CONTAINER(ani_timing_hbox) , 6 ); gtk_container_add( GTK_CONTAINER(ani_timing_frame) , ani_timing_hbox ); - gtk_box_pack_start( GTK_BOX(ani_vbox) , ani_timing_frame , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(ani_vbox) , ani_timing_frame , false , false , 0 ); ani_timing_stay_widget = aosd_ui_configure_animation_timing( _("Display:") ); gtk_spin_button_set_value( GTK_SPIN_BUTTON(g_object_get_data( G_OBJECT(ani_timing_stay_widget),"spinbt")) , cfg->animation.timing_display ); - gtk_box_pack_start( GTK_BOX(ani_timing_hbox) , ani_timing_stay_widget , TRUE , TRUE , 0 ); - gtk_box_pack_start( GTK_BOX(ani_timing_hbox) , gtk_vseparator_new() , FALSE , FALSE , 4 ); + gtk_box_pack_start( GTK_BOX(ani_timing_hbox) , ani_timing_stay_widget , true , true , 0 ); + gtk_box_pack_start( GTK_BOX(ani_timing_hbox) , gtk_vseparator_new() , false , false , 4 ); ani_timing_fadein_widget = aosd_ui_configure_animation_timing( _("Fade in:") ); gtk_spin_button_set_value( GTK_SPIN_BUTTON(g_object_get_data( G_OBJECT(ani_timing_fadein_widget),"spinbt")) , cfg->animation.timing_fadein ); - gtk_box_pack_start( GTK_BOX(ani_timing_hbox) , ani_timing_fadein_widget , TRUE , TRUE , 0 ); - gtk_box_pack_start( GTK_BOX(ani_timing_hbox) , gtk_vseparator_new() , FALSE , FALSE , 4 ); + gtk_box_pack_start( GTK_BOX(ani_timing_hbox) , ani_timing_fadein_widget , true , true , 0 ); + gtk_box_pack_start( GTK_BOX(ani_timing_hbox) , gtk_vseparator_new() , false , false , 4 ); ani_timing_fadeout_widget = aosd_ui_configure_animation_timing( _("Fade out:") ); gtk_spin_button_set_value( GTK_SPIN_BUTTON(g_object_get_data( G_OBJECT(ani_timing_fadeout_widget),"spinbt")) , cfg->animation.timing_fadeout ); - gtk_box_pack_start( GTK_BOX(ani_timing_hbox) , ani_timing_fadeout_widget , TRUE , TRUE , 0 ); + gtk_box_pack_start( GTK_BOX(ani_timing_hbox) , ani_timing_fadeout_widget , true , true , 0 ); g_object_set_data( G_OBJECT(ani_timing_hbox) , "display" , g_object_get_data(G_OBJECT(ani_timing_stay_widget),"spinbt") ); g_object_set_data( G_OBJECT(ani_timing_hbox) , "fadein" , @@ -318,10 +318,10 @@ static void aosd_cb_configure_text_font_shadow_toggle ( GtkToggleButton * shadow_togglebt , void * shadow_colorbt ) { - if ( gtk_toggle_button_get_active( shadow_togglebt ) == TRUE ) - gtk_widget_set_sensitive( GTK_WIDGET(shadow_colorbt) , TRUE ); + if ( gtk_toggle_button_get_active( shadow_togglebt ) == true ) + gtk_widget_set_sensitive( GTK_WIDGET(shadow_colorbt) , true ); else - gtk_widget_set_sensitive( GTK_WIDGET(shadow_colorbt) , FALSE ); + gtk_widget_set_sensitive( GTK_WIDGET(shadow_colorbt) , false ); } @@ -355,11 +355,11 @@ aosd_ui_configure_text ( aosd_cfg_t * cfg ) GtkWidget *tex_font_shadow_colorbt[3]; int i = 0; - tex_vbox = gtk_vbox_new( FALSE , 4 ); + tex_vbox = gtk_vbox_new( false , 4 ); gtk_container_set_border_width( GTK_CONTAINER(tex_vbox) , 6 ); tex_font_frame = gtk_frame_new( _("Fonts") ); - tex_font_grid = gtk_table_new (0, 0, FALSE); + tex_font_grid = gtk_table_new (0, 0, false); gtk_container_set_border_width( GTK_CONTAINER(tex_font_grid) , 6 ); gtk_table_set_row_spacings( GTK_TABLE(tex_font_grid) , 4 ); gtk_table_set_col_spacings( GTK_TABLE(tex_font_grid) , 4 ); @@ -369,10 +369,10 @@ aosd_ui_configure_text ( aosd_cfg_t * cfg ) tex_font_label[i] = gtk_label_new( label_str ); g_free( label_str ); tex_font_fontbt[i] = gtk_font_button_new(); - gtk_font_button_set_show_style( GTK_FONT_BUTTON(tex_font_fontbt[i]) , TRUE ); - gtk_font_button_set_show_size( GTK_FONT_BUTTON(tex_font_fontbt[i]) , TRUE ); - gtk_font_button_set_use_font( GTK_FONT_BUTTON(tex_font_fontbt[i]) , FALSE ); - gtk_font_button_set_use_size( GTK_FONT_BUTTON(tex_font_fontbt[i]) , FALSE ); + gtk_font_button_set_show_style( GTK_FONT_BUTTON(tex_font_fontbt[i]) , true ); + gtk_font_button_set_show_size( GTK_FONT_BUTTON(tex_font_fontbt[i]) , true ); + gtk_font_button_set_use_font( GTK_FONT_BUTTON(tex_font_fontbt[i]) , false ); + gtk_font_button_set_use_size( GTK_FONT_BUTTON(tex_font_fontbt[i]) , false ); gtk_font_button_set_font_name( GTK_FONT_BUTTON(tex_font_fontbt[i]) , cfg->text.fonts_name[i] ); tex_font_colorbt[i] = gtk_color_button_new (); @@ -380,13 +380,13 @@ aosd_ui_configure_text ( aosd_cfg_t * cfg ) & cfg->text.fonts_color[i]); tex_font_shadow_togglebt[i] = gtk_toggle_button_new_with_label( _("Shadow") ); - gtk_toggle_button_set_mode( GTK_TOGGLE_BUTTON(tex_font_shadow_togglebt[i]) , FALSE ); + gtk_toggle_button_set_mode( GTK_TOGGLE_BUTTON(tex_font_shadow_togglebt[i]) , false ); tex_font_shadow_colorbt[i] = gtk_color_button_new (); chooser_set_aosd_color ((GtkColorButton *) tex_font_shadow_colorbt[i], & cfg->text.fonts_shadow_color[i]); - gtk_widget_set_sensitive( tex_font_shadow_colorbt[i] , FALSE ); + gtk_widget_set_sensitive( tex_font_shadow_colorbt[i] , false ); g_signal_connect( G_OBJECT(tex_font_shadow_togglebt[i]) , "toggled" , G_CALLBACK(aosd_cb_configure_text_font_shadow_toggle) , tex_font_shadow_colorbt[i] ); @@ -404,7 +404,7 @@ aosd_ui_configure_text ( aosd_cfg_t * cfg ) aosd_cb_list.append( tex_font_fontbt[i] , aosd_cb_configure_text_font_commit ); } gtk_container_add( GTK_CONTAINER(tex_font_frame) , tex_font_grid ); - gtk_box_pack_start( GTK_BOX(tex_vbox) , tex_font_frame , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(tex_vbox) , tex_font_frame , false , false , 0 ); return tex_vbox; } @@ -417,7 +417,7 @@ aosd_cb_configure_decoration_style_commit ( GtkWidget * lv , aosd_cfg_t * cfg ) GtkTreeModel *model; GtkTreeIter iter; - if ( gtk_tree_selection_get_selected( sel , &model , &iter ) == TRUE ) + if ( gtk_tree_selection_get_selected( sel , &model , &iter ) == true ) { int deco_code = 0; gtk_tree_model_get( model , &iter , 1 , &deco_code , -1 ); @@ -451,7 +451,7 @@ aosd_ui_configure_decoration ( aosd_cfg_t * cfg ) GtkWidget *dec_rstyleopts_frame, *dec_rstyleopts_grid; int colors_max_num = 0, i = 0; - dec_hbox = gtk_hbox_new( FALSE , 4 ); + dec_hbox = gtk_hbox_new( false , 4 ); gtk_container_set_border_width( GTK_CONTAINER(dec_hbox) , 6 ); /* decoration style model @@ -492,15 +492,15 @@ aosd_ui_configure_decoration ( aosd_cfg_t * cfg ) gtk_container_add( GTK_CONTAINER(dec_rstyle_lv_frame) , dec_rstyle_lv_sw ); gtk_tree_selection_select_iter( dec_rstyle_lv_sel , &iter_sel ); - gtk_box_pack_start( GTK_BOX(dec_hbox) , dec_rstyle_lv_frame , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(dec_hbox) , dec_rstyle_lv_frame , false , false , 0 ); aosd_cb_list.append( dec_rstyle_lv , aosd_cb_configure_decoration_style_commit ); - dec_rstyle_hbox = gtk_vbox_new( FALSE , 4 ); - gtk_box_pack_start( GTK_BOX(dec_hbox) , dec_rstyle_hbox , TRUE , TRUE , 0 ); + dec_rstyle_hbox = gtk_vbox_new( false , 4 ); + gtk_box_pack_start( GTK_BOX(dec_hbox) , dec_rstyle_hbox , true , true , 0 ); /* in colors_max_num now there's the maximum number of colors used by decoration styles */ dec_rstyleopts_frame = gtk_frame_new( _("Colors") ); - dec_rstyleopts_grid = gtk_table_new (0, 0, FALSE); + dec_rstyleopts_grid = gtk_table_new (0, 0, false); gtk_container_set_border_width( GTK_CONTAINER(dec_rstyleopts_grid) , 6 ); gtk_table_set_row_spacings( GTK_TABLE(dec_rstyleopts_grid) , 4 ); gtk_table_set_col_spacings( GTK_TABLE(dec_rstyleopts_grid) , 8 ); @@ -509,7 +509,7 @@ aosd_ui_configure_decoration ( aosd_cfg_t * cfg ) { GtkWidget *hbox, *label; char *label_str = nullptr; - hbox = gtk_hbox_new( FALSE , 4 ); + hbox = gtk_hbox_new( false , 4 ); label_str = g_strdup_printf( _("Color %i:") , i+1 ); label = gtk_label_new( label_str ); g_free( label_str ); @@ -517,13 +517,13 @@ aosd_ui_configure_decoration ( aosd_cfg_t * cfg ) GtkWidget * colorbt = gtk_color_button_new (); chooser_set_aosd_color ((GtkColorButton *) colorbt, & cfg->decoration.colors[i]); - gtk_box_pack_start( GTK_BOX(hbox) , label , FALSE , FALSE , 0 ); - gtk_box_pack_start( GTK_BOX(hbox) , colorbt , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(hbox) , label , false , false , 0 ); + gtk_box_pack_start( GTK_BOX(hbox) , colorbt , false , false , 0 ); gtk_table_attach_defaults( GTK_TABLE(dec_rstyleopts_grid) , hbox , (i % 3) , (i % 3) + 1, (i / 3) , (i / 3) + 1); g_object_set_data( G_OBJECT(colorbt) , "colnum" , GINT_TO_POINTER(i) ); aosd_cb_list.append( colorbt , aosd_cb_configure_decoration_color_commit ); } - gtk_box_pack_start( GTK_BOX(dec_rstyle_hbox) , dec_rstyleopts_frame , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(dec_rstyle_hbox) , dec_rstyleopts_frame , false , false , 0 ); return dec_hbox; } @@ -535,7 +535,7 @@ aosd_cb_configure_trigger_lvchanged ( GtkTreeSelection *sel , void * nb ) GtkTreeModel *model; GtkTreeIter iter; - if ( gtk_tree_selection_get_selected( sel , &model , &iter ) == TRUE ) + if ( gtk_tree_selection_get_selected( sel , &model , &iter ) == true ) { int page_num = 0; gtk_tree_model_get( model , &iter , 2 , &page_num , -1 ); @@ -547,7 +547,7 @@ aosd_cb_configure_trigger_lvchanged ( GtkTreeSelection *sel , void * nb ) static void aosd_cb_configure_trigger_commit ( GtkWidget * cbt , aosd_cfg_t * cfg ) { - if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(cbt) ) == TRUE ) + if ( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON(cbt) ) == true ) { int value = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(cbt),"code")); cfg->trigger.enabled[value] = true; @@ -570,10 +570,10 @@ aosd_ui_configure_trigger ( aosd_cfg_t * cfg ) tri_event_nb = gtk_notebook_new(); gtk_notebook_set_tab_pos( GTK_NOTEBOOK(tri_event_nb) , GTK_POS_LEFT ); - gtk_notebook_set_show_tabs( GTK_NOTEBOOK(tri_event_nb) , FALSE ); - gtk_notebook_set_show_border( GTK_NOTEBOOK(tri_event_nb) , FALSE ); + gtk_notebook_set_show_tabs( GTK_NOTEBOOK(tri_event_nb) , false ); + gtk_notebook_set_show_border( GTK_NOTEBOOK(tri_event_nb) , false ); - tri_hbox = gtk_hbox_new( FALSE , 4 ); + tri_hbox = gtk_hbox_new( false , 4 ); gtk_container_set_border_width( GTK_CONTAINER(tri_hbox) , 6 ); /* trigger model @@ -591,20 +591,20 @@ aosd_ui_configure_trigger ( aosd_cfg_t * cfg ) gtk_list_store_set( tri_event_store , &iter , 0 , _(aosd_trigger_get_name( i )) , 1 , i , 2 , i , -1 ); - vbox = gtk_vbox_new( FALSE , 0 ); + vbox = gtk_vbox_new( false , 0 ); gtk_container_set_border_width( GTK_CONTAINER(vbox) , 6 ); label = gtk_label_new( _(aosd_trigger_get_desc( i )) ); - gtk_label_set_line_wrap( GTK_LABEL(label) , TRUE ); + gtk_label_set_line_wrap( GTK_LABEL(label) , true ); gtk_label_set_max_width_chars( GTK_LABEL(label), 40 ); gtk_misc_set_alignment( GTK_MISC(label) , 0.0 , 0.0 ); checkbt = gtk_check_button_new_with_label( _("Enable trigger") ); if ( cfg->trigger.enabled[i] ) - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(checkbt) , TRUE ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(checkbt) , true ); else - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(checkbt) , FALSE ); - gtk_box_pack_start( GTK_BOX(vbox) , checkbt , FALSE , FALSE , 0 ); - gtk_box_pack_start( GTK_BOX(vbox) , gtk_hseparator_new() , FALSE , FALSE , 4 ); - gtk_box_pack_start( GTK_BOX(vbox) , label , FALSE , FALSE , 0 ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(checkbt) , false ); + gtk_box_pack_start( GTK_BOX(vbox) , checkbt , false , false , 0 ); + gtk_box_pack_start( GTK_BOX(vbox) , gtk_hseparator_new() , false , false , 4 ); + gtk_box_pack_start( GTK_BOX(vbox) , label , false , false , 0 ); frame = gtk_frame_new( nullptr ); gtk_container_add( GTK_CONTAINER(frame) , vbox ); gtk_notebook_append_page( GTK_NOTEBOOK(tri_event_nb) , frame , nullptr ); @@ -619,7 +619,7 @@ aosd_ui_configure_trigger ( aosd_cfg_t * cfg ) gtk_tree_selection_set_mode( tri_event_lv_sel , GTK_SELECTION_BROWSE ); g_signal_connect( G_OBJECT(tri_event_lv_sel) , "changed" , G_CALLBACK(aosd_cb_configure_trigger_lvchanged) , tri_event_nb ); - if ( gtk_tree_model_get_iter_first( GTK_TREE_MODEL(tri_event_store) , &iter ) == TRUE ) + if ( gtk_tree_model_get_iter_first( GTK_TREE_MODEL(tri_event_store) , &iter ) == true ) gtk_tree_selection_select_iter( tri_event_lv_sel , &iter ); tri_event_lv_rndr_text = gtk_cell_renderer_text_new(); @@ -633,9 +633,9 @@ aosd_ui_configure_trigger ( aosd_cfg_t * cfg ) gtk_container_add( GTK_CONTAINER(tri_event_lv_frame) , tri_event_lv_sw ); gtk_tree_selection_select_iter( tri_event_lv_sel , &iter ); - gtk_box_pack_start( GTK_BOX(tri_hbox) , tri_event_lv_frame , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(tri_hbox) , tri_event_lv_frame , false , false , 0 ); - gtk_box_pack_start( GTK_BOX(tri_hbox) , tri_event_nb , TRUE , TRUE , 0 ); + gtk_box_pack_start( GTK_BOX(tri_hbox) , tri_event_nb , true , true , 0 ); return tri_hbox; } @@ -653,7 +653,7 @@ aosd_cb_configure_misc_transp_real_clicked ( GtkToggleButton * real_rbt , void * { gtk_image_set_from_icon_name( GTK_IMAGE(img) , "face-smile" , GTK_ICON_SIZE_MENU ); gtk_label_set_text( GTK_LABEL(label) , _("Composite manager detected") ); - gtk_widget_set_sensitive( GTK_WIDGET(status_hbox) , TRUE ); + gtk_widget_set_sensitive( GTK_WIDGET(status_hbox) , true ); } else { @@ -661,14 +661,14 @@ aosd_cb_configure_misc_transp_real_clicked ( GtkToggleButton * real_rbt , void * gtk_label_set_text( GTK_LABEL(label) , _("Composite manager not detected;\nunless you know that you have one running, " "please activate a composite manager otherwise the OSD won't work properly") ); - gtk_widget_set_sensitive( GTK_WIDGET(status_hbox) , TRUE ); + gtk_widget_set_sensitive( GTK_WIDGET(status_hbox) , true ); } } else { gtk_image_set_from_icon_name( GTK_IMAGE(img) , "dialog-information" , GTK_ICON_SIZE_MENU ); gtk_label_set_text( GTK_LABEL(label) , _("Composite manager not required for fake transparency") ); - gtk_widget_set_sensitive( GTK_WIDGET(status_hbox) , FALSE ); + gtk_widget_set_sensitive( GTK_WIDGET(status_hbox) , false ); } } #endif @@ -699,14 +699,14 @@ aosd_ui_configure_misc ( aosd_cfg_t * cfg ) GtkWidget *mis_transp_status_frame, *mis_transp_status_hbox; GtkWidget *mis_transp_status_img, *mis_transp_status_label; - mis_vbox = gtk_vbox_new( FALSE , 0 ); + mis_vbox = gtk_vbox_new( false , 0 ); gtk_container_set_border_width( GTK_CONTAINER(mis_vbox) , 6 ); - mis_transp_vbox = gtk_vbox_new( FALSE , 0 ); + mis_transp_vbox = gtk_vbox_new( false , 0 ); mis_transp_frame = gtk_frame_new( _("Transparency") ); gtk_container_set_border_width( GTK_CONTAINER(mis_transp_vbox) , 6 ); gtk_container_add( GTK_CONTAINER(mis_transp_frame) , mis_transp_vbox ); - gtk_box_pack_start( GTK_BOX(mis_vbox) , mis_transp_frame , FALSE , FALSE , 0 ); + gtk_box_pack_start( GTK_BOX(mis_vbox) , mis_transp_frame , false , false , 0 ); mis_transp_fake_rbt = gtk_radio_button_new_with_label( nullptr , _("Fake transparency") ); @@ -716,22 +716,22 @@ aosd_ui_configure_misc ( aosd_cfg_t * cfg ) GINT_TO_POINTER(AOSD_MISC_TRANSPARENCY_FAKE) ); g_object_set_data( G_OBJECT(mis_transp_real_rbt) , "val" , GINT_TO_POINTER(AOSD_MISC_TRANSPARENCY_REAL) ); - gtk_box_pack_start( GTK_BOX(mis_transp_vbox) , mis_transp_fake_rbt , TRUE , TRUE , 0 ); - gtk_box_pack_start( GTK_BOX(mis_transp_vbox) , mis_transp_real_rbt , TRUE , TRUE , 0 ); + gtk_box_pack_start( GTK_BOX(mis_transp_vbox) , mis_transp_fake_rbt , true , true , 0 ); + gtk_box_pack_start( GTK_BOX(mis_transp_vbox) , mis_transp_real_rbt , true , true , 0 ); - mis_transp_status_hbox = gtk_hbox_new( FALSE , 4 ); + mis_transp_status_hbox = gtk_hbox_new( false , 4 ); mis_transp_status_frame = gtk_frame_new( nullptr ); gtk_container_set_border_width( GTK_CONTAINER(mis_transp_status_hbox) , 3 ); gtk_container_add( GTK_CONTAINER(mis_transp_status_frame) , mis_transp_status_hbox ); - gtk_box_pack_start( GTK_BOX(mis_transp_vbox) , mis_transp_status_frame , TRUE , TRUE , 0 ); + gtk_box_pack_start( GTK_BOX(mis_transp_vbox) , mis_transp_status_frame , true , true , 0 ); mis_transp_status_img = gtk_image_new(); gtk_misc_set_alignment( GTK_MISC(mis_transp_status_img) , 0.5 , 0 ); mis_transp_status_label = gtk_label_new( "" ); gtk_misc_set_alignment( GTK_MISC(mis_transp_status_label) , 0 , 0.5 ); - gtk_label_set_line_wrap( GTK_LABEL(mis_transp_status_label) , TRUE ); - gtk_box_pack_start( GTK_BOX(mis_transp_status_hbox) , mis_transp_status_img , FALSE , FALSE , 0 ); - gtk_box_pack_start( GTK_BOX(mis_transp_status_hbox) , mis_transp_status_label , TRUE , TRUE , 0 ); + gtk_label_set_line_wrap( GTK_LABEL(mis_transp_status_label) , true ); + gtk_box_pack_start( GTK_BOX(mis_transp_status_hbox) , mis_transp_status_img , false , false , 0 ); + gtk_box_pack_start( GTK_BOX(mis_transp_status_hbox) , mis_transp_status_label , true , true , 0 ); g_object_set_data( G_OBJECT(mis_transp_status_hbox) , "img" , mis_transp_status_img ); g_object_set_data( G_OBJECT(mis_transp_status_hbox) , "label" , mis_transp_status_label ); @@ -743,26 +743,26 @@ aosd_ui_configure_misc ( aosd_cfg_t * cfg ) if ( aosd_osd_check_composite_ext() ) { if ( cfg->misc.transparency_mode == AOSD_MISC_TRANSPARENCY_FAKE ) - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(mis_transp_fake_rbt) , TRUE ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(mis_transp_fake_rbt) , true ); else - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(mis_transp_real_rbt) , TRUE ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(mis_transp_real_rbt) , true ); } else { - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(mis_transp_fake_rbt) , TRUE ); - gtk_widget_set_sensitive( GTK_WIDGET(mis_transp_real_rbt) , FALSE ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(mis_transp_fake_rbt) , true ); + gtk_widget_set_sensitive( GTK_WIDGET(mis_transp_real_rbt) , false ); gtk_image_set_from_icon_name( GTK_IMAGE(mis_transp_status_img) , "dialog-error" , GTK_ICON_SIZE_MENU ); gtk_label_set_text( GTK_LABEL(mis_transp_status_label) , _("Composite extension not loaded") ); - gtk_widget_set_sensitive( GTK_WIDGET(mis_transp_status_hbox) , FALSE ); + gtk_widget_set_sensitive( GTK_WIDGET(mis_transp_status_hbox) , false ); } #else - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(mis_transp_fake_rbt) , TRUE ); - gtk_widget_set_sensitive( GTK_WIDGET(mis_transp_real_rbt) , FALSE ); + gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(mis_transp_fake_rbt) , true ); + gtk_widget_set_sensitive( GTK_WIDGET(mis_transp_real_rbt) , false ); gtk_image_set_from_icon_name( GTK_IMAGE(mis_transp_status_img) , "dialog-error" , GTK_ICON_SIZE_MENU ); gtk_label_set_text( GTK_LABEL(mis_transp_status_label) , _("Composite extension not available") ); - gtk_widget_set_sensitive( GTK_WIDGET(mis_transp_status_hbox) , FALSE ); + gtk_widget_set_sensitive( GTK_WIDGET(mis_transp_status_hbox) , false ); #endif aosd_cb_list.append( mis_transp_vbox , aosd_cb_configure_misc_transp_commit ); diff --git a/src/blur_scope/blur_scope.cc b/src/blur_scope/blur_scope.cc index 279009d..c5c08df 100644 --- a/src/blur_scope/blur_scope.cc +++ b/src/blur_scope/blur_scope.cc @@ -28,15 +28,13 @@ #include <gtk/gtk.h> +#define AUD_PLUGIN_GLIB_ONLY #include <libaudcore/i18n.h> #include <libaudcore/runtime.h> #include <libaudcore/plugin.h> #include <libaudcore/preferences.h> -#define D_WIDTH 64 -#define D_HEIGHT 32 - -static void /* GtkWidget */ * bscope_get_color_chooser (void); +static void /* GtkWidget */ * bscope_get_color_chooser (); static const PreferencesWidget bscope_widgets[] = { WidgetLabel (N_("<b>Color</b>")), @@ -46,7 +44,7 @@ static const PreferencesWidget bscope_widgets[] = { static const PluginPreferences bscope_prefs = {{bscope_widgets}}; static const char * const bscope_defaults[] = { - "color", "16727935", /* 0xFF3F7F */ + "color", aud::numeric_string<0xFF3F7F>::str, nullptr}; static int bscope_color; @@ -93,7 +91,7 @@ bool BlurScope::init () aud_config_set_defaults ("BlurScope", bscope_defaults); bscope_color = aud_get_int ("BlurScope", "color"); - return TRUE; + return true; } void BlurScope::cleanup () @@ -132,20 +130,18 @@ void BlurScope::draw () gboolean BlurScope::configure_event (GtkWidget * widget, GdkEventConfigure * event, void * user) { ((BlurScope *) user)->resize (event->width, event->height); - return TRUE; + return true; } gboolean BlurScope::expose_event (GtkWidget * widget, GdkEventExpose * event, void * user) { ((BlurScope *) user)->draw (); - return TRUE; + return true; } void * BlurScope::get_gtk_widget () { area = gtk_drawing_area_new (); - gtk_widget_set_size_request (area, D_WIDTH, D_HEIGHT); - resize (D_WIDTH, D_HEIGHT); g_signal_connect (area, "expose-event", (GCallback) expose_event, this); g_signal_connect (area, "configure-event", (GCallback) configure_event, this); @@ -221,12 +217,12 @@ static void color_set_cb (GtkWidget * chooser) bscope_color = ((gdk_color.red & 0xff00) << 8) | (gdk_color.green & 0xff00) | (gdk_color.blue >> 8); } -static void /* GtkWidget */ * bscope_get_color_chooser (void) +static void /* GtkWidget */ * bscope_get_color_chooser () { GdkColor gdk_color = {0, (uint16_t) ((bscope_color & 0xff0000) >> 8), (uint16_t) (bscope_color & 0xff00), (uint16_t) ((bscope_color & 0xff) << 8)}; GtkWidget * chooser = gtk_color_button_new_with_color (& gdk_color); - gtk_color_button_set_use_alpha ((GtkColorButton *) chooser, FALSE); + gtk_color_button_set_use_alpha ((GtkColorButton *) chooser, false); g_signal_connect (chooser, "color-set", (GCallback) color_set_cb, nullptr); diff --git a/src/cairo-spectrum/cairo-spectrum.cc b/src/cairo-spectrum/cairo-spectrum.cc index 11f87ff..8709402 100644 --- a/src/cairo-spectrum/cairo-spectrum.cc +++ b/src/cairo-spectrum/cairo-spectrum.cc @@ -23,6 +23,7 @@ #include <gtk/gtk.h> +#define AUD_PLUGIN_GLIB_ONLY #include <libaudcore/hook.h> #include <libaudcore/i18n.h> #include <libaudcore/interface.h> @@ -236,7 +237,7 @@ static gboolean configure_event (GtkWidget * widget, GdkEventConfigure * event) bands = aud::clamp(bands, 12, MAX_BANDS); calculate_xscale (); - return TRUE; + return true; } static gboolean draw_event (GtkWidget * widget) @@ -247,7 +248,7 @@ static gboolean draw_event (GtkWidget * widget) draw_visualizer (widget, cr); cairo_destroy (cr); - return TRUE; + return true; } void * CairoSpectrum::get_gtk_widget () diff --git a/src/cd-menu-items/Makefile b/src/cd-menu-items/Makefile index 824a9d1..836093b 100644 --- a/src/cd-menu-items/Makefile +++ b/src/cd-menu-items/Makefile @@ -8,6 +8,5 @@ include ../../extra.mk plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR} LD = ${CXX} -CPPFLAGS += -I../.. ${GTK_CFLAGS} +CPPFLAGS += -I../.. CFLAGS += ${PLUGIN_CFLAGS} -LIBS += ${GTK_LIBS} diff --git a/src/cd-menu-items/cd-menu-items.cc b/src/cd-menu-items/cd-menu-items.cc index 0719fc4..e3defd9 100644 --- a/src/cd-menu-items/cd-menu-items.cc +++ b/src/cd-menu-items/cd-menu-items.cc @@ -17,8 +17,6 @@ * the use of this software. */ -#include <gtk/gtk.h> - #include <libaudcore/audstrings.h> #include <libaudcore/drct.h> #include <libaudcore/i18n.h> @@ -62,7 +60,7 @@ bool CDMenuItems::init () for (int i = 0; i < N_ITEMS; i ++) aud_plugin_menu_add (menus[m], funcs[i], _(titles[i]), "media-optical"); - return TRUE; + return true; } void CDMenuItems::cleanup () diff --git a/src/cdaudio-ng/cdaudio-ng.cc b/src/cdaudio-ng/cdaudio-ng.cc index 6ac85ed..ca628ce 100644 --- a/src/cdaudio-ng/cdaudio-ng.cc +++ b/src/cdaudio-ng/cdaudio-ng.cc @@ -46,7 +46,6 @@ #include <libaudcore/hook.h> #include <libaudcore/i18n.h> #include <libaudcore/interface.h> -#include <libaudcore/mainloop.h> #include <libaudcore/playlist.h> #include <libaudcore/plugin.h> #include <libaudcore/preferences.h> @@ -109,7 +108,6 @@ static int lasttrackno = -1; static int n_audio_tracks; static cdrom_drive_t *pcdrom_drive = nullptr; static Index<trackinfo_t> trackinfo; -static QueuedFunc monitor_source; static bool scan_cd (); static void refresh_trackinfo (bool warning); @@ -223,7 +221,7 @@ static void monitor (void *) return; } - monitor_source.stop (); + timer_remove (TimerRate::Hz1, monitor); pthread_mutex_unlock (& mutex); purge_all_playlists (); @@ -232,8 +230,7 @@ static void monitor (void *) /* mutex must be locked */ static void trigger_monitor () { - if (! monitor_source.running ()) - monitor_source.start (1000, monitor, nullptr); + timer_add (TimerRate::Hz1, monitor); } /* main thread only */ @@ -785,7 +782,7 @@ static void refresh_trackinfo (bool warning) /* mutex must be locked */ static void reset_trackinfo () { - monitor_source.stop (); + timer_remove (TimerRate::Hz1, monitor); if (pcdrom_drive != nullptr) { diff --git a/src/coreaudio/coreaudio.cc b/src/coreaudio/coreaudio.cc index e2af9b3..6211db4 100644 --- a/src/coreaudio/coreaudio.cc +++ b/src/coreaudio/coreaudio.cc @@ -151,7 +151,7 @@ const PluginPreferences CoreAudioPlugin::prefs = { nullptr }; -bool CoreAudioPlugin::init (void) +bool CoreAudioPlugin::init () { aud_config_set_defaults ("coreaudio", defaults); @@ -166,7 +166,7 @@ bool CoreAudioPlugin::init (void) desc.componentFlagsMask = 0; desc.componentManufacturer = 0; - output_comp = AudioComponentFindNext (NULL, & desc); + output_comp = AudioComponentFindNext (nullptr, & desc); if (! output_comp) { error ("Failed to open default audio device.\n"); @@ -192,7 +192,7 @@ bool CoreAudioPlugin::init (void) return 1; } -void CoreAudioPlugin::cleanup (void) +void CoreAudioPlugin::cleanup () { } @@ -317,7 +317,7 @@ bool CoreAudioPlugin::open_audio (int format, int rate_, int chan_) prop.mScope = kAudioObjectPropertyScopeGlobal; prop.mElement = kAudioObjectPropertyElementMaster; - OSStatus err = AudioObjectSetPropertyData (kAudioObjectSystemObject, & prop, 0, NULL, sizeof hog_mode, & hog_mode); + OSStatus err = AudioObjectSetPropertyData (kAudioObjectSystemObject, & prop, 0, nullptr, sizeof hog_mode, & hog_mode); if (err != noErr) { AUDWARN ("Failed to open device for exclusive mode, continuing anyway... [%d]\n", err); @@ -353,7 +353,7 @@ void CoreAudioPlugin::close_audio () prop.mScope = kAudioObjectPropertyScopeGlobal; prop.mElement = kAudioObjectPropertyElementMaster; - OSStatus err = AudioObjectSetPropertyData (kAudioObjectSystemObject, & prop, 0, NULL, sizeof hog_mode, & hog_mode); + OSStatus err = AudioObjectSetPropertyData (kAudioObjectSystemObject, & prop, 0, nullptr, sizeof hog_mode, & hog_mode); if (err != noErr) AUDWARN ("Failed to release device from exclusive mode, continuing anyway..."); diff --git a/src/crossfade/crossfade.cc b/src/crossfade/crossfade.cc index b7b15d7..d2b1825 100644 --- a/src/crossfade/crossfade.cc +++ b/src/crossfade/crossfade.cc @@ -18,7 +18,6 @@ */ #include <libaudcore/i18n.h> -#include <libaudcore/interface.h> #include <libaudcore/plugin.h> #include <libaudcore/preferences.h> #include <libaudcore/runtime.h> @@ -91,19 +90,10 @@ public: EXPORT Crossfade aud_plugin_instance; static char state = STATE_OFF; -static int current_channels = 0, current_rate = 0; +static int current_channels, current_rate; static Index<float> buffer, output; static int fadein_point; -static void reset () -{ - state = STATE_OFF; - current_channels = 0; - current_rate = 0; - buffer.clear (); - output.clear (); -} - bool Crossfade::init () { aud_config_set_defaults ("crossfade", crossfade_defaults); @@ -112,7 +102,9 @@ bool Crossfade::init () void Crossfade::cleanup () { - reset (); + state = STATE_OFF; + buffer.clear (); + output.clear (); } static void do_ramp (float * data, int length, float a, float b) @@ -130,6 +122,35 @@ static void mix (float * data, float * add, int length) (* data ++) += (* add ++); } +/* stupid simple resampling/rechanneling algorithm */ +static void reformat (int channels, int rate) +{ + if (channels == current_channels && rate == current_rate) + return; + + int old_frames = buffer.len () / current_channels; + int new_frames = (int64_t) old_frames * rate / current_rate; + + int map[AUD_MAX_CHANNELS]; + for (int c = 0; c < channels; c ++) + map[c] = c * current_channels / channels; + + Index<float> new_buffer; + new_buffer.resize (new_frames * channels); + + for (int f = 0; f < new_frames; f ++) + { + int f0 = (int64_t) f * current_rate / rate; + int s0 = f0 * current_channels; + int s = f * channels; + + for (int c = 0; c < channels; c ++) + new_buffer[s + c] = buffer[s0 + map[c]]; + } + + buffer = std::move (new_buffer); +} + static int buffer_needed_for_state () { double overlap = 0; @@ -155,30 +176,13 @@ static void output_data_as_ready (int buffer_needed, bool exact) void Crossfade::start (int & channels, int & rate) { if (state != STATE_OFF) - { - if (channels != current_channels) - { - aud_ui_show_error (_("Crossfading failed because the songs had " - "a different number of channels. You can use the Channel Mixer to " - "convert the songs to the same number of channels.")); - state = STATE_OFF; - } - else if (rate != current_rate) - { - aud_ui_show_error (_("Crossfading failed because the songs had " - "different sample rates. You can use the Sample Rate Converter to " - "convert the songs to the same sample rate.")); - state = STATE_OFF; - } - } + reformat (channels, rate); + + current_channels = channels; + current_rate = rate; if (state == STATE_OFF) { - reset (); - - current_channels = channels; - current_rate = rate; - if (aud_get_bool ("crossfade", "manual")) { state = STATE_FLUSHED; diff --git a/src/cue/cue.cc b/src/cue/cue.cc index 79de658..f733f28 100644 --- a/src/cue/cue.cc +++ b/src/cue/cue.cc @@ -1,6 +1,6 @@ /* * Cue Sheet Plugin for Audacious - * Copyright (c) 2009-2011 William Pitcock and John Lindgren + * Copyright (c) 2009-2015 William Pitcock and John Lindgren * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -17,7 +17,6 @@ * the use of this software. */ -#include <stdlib.h> #include <string.h> extern "C" { @@ -35,7 +34,6 @@ class CueLoader : public PlaylistPlugin { public: static constexpr PluginInfo info = {N_("Cue Sheet Plugin"), PACKAGE}; - constexpr CueLoader () : PlaylistPlugin (info, cue_exts, false) {} bool load (const char * filename, VFSFile & file, String & title, @@ -44,31 +42,6 @@ public: EXPORT CueLoader aud_plugin_instance; -static const struct { - Tuple::Field field; - int pti; -} pti_map[] = { - { Tuple::Artist, PTI_PERFORMER }, - { Tuple::Title, PTI_TITLE }, -}; - -static void -tuple_attach_cdtext(Tuple &tuple, Track *track, Tuple::Field field, int pti) -{ - Cdtext *cdtext; - const char *text; - - cdtext = track_get_cdtext(track); - if (cdtext == nullptr) - return; - - text = cdtext_get(pti, cdtext); - if (text == nullptr) - return; - - tuple.set_str (field, text); -} - bool CueLoader::load (const char * cue_filename, VFSFile & file, String & title, Index<PlaylistAddItem> & items) { @@ -76,79 +49,80 @@ bool CueLoader::load (const char * cue_filename, VFSFile & file, String & title, if (! buffer.len ()) return false; - buffer.append (0); /* null-terminated */ + buffer.append (0); /* null-terminate */ Cd * cd = cue_parse_string (buffer.begin ()); - if (cd == nullptr) - return false; + int tracks = cd ? cd_get_ntrack (cd) : 0; - int tracks = cd_get_ntrack (cd); - if (tracks == 0) + if (tracks < 1) return false; - Track * current = cd_get_track (cd, 1); - if (current == nullptr) - return false; + Track * cur = cd_get_track (cd, 1); + const char * cur_name = cur ? track_get_filename (cur) : nullptr; - char * track_filename = track_get_filename (current); - if (track_filename == nullptr) + if (! cur_name) return false; - String filename = String (uri_construct (track_filename, cue_filename)); - + bool new_file = true; + String filename; + PluginHandle * decoder = nullptr; Tuple base_tuple; - bool base_tuple_scanned = false; for (int track = 1; track <= tracks; track ++) { - if (current == nullptr || ! filename) - return false; - - if (! base_tuple_scanned) + if (new_file) { - base_tuple_scanned = true; - PluginHandle * decoder = aud_file_find_decoder (filename, false); - if (decoder != nullptr) - base_tuple = aud_file_read_tuple (filename, decoder); + filename = String (uri_construct (cur_name, cue_filename)); + decoder = filename ? aud_file_find_decoder (filename, false) : nullptr; + base_tuple = decoder ? aud_file_read_tuple (filename, decoder) : Tuple (); } Track * next = (track + 1 <= tracks) ? cd_get_track (cd, track + 1) : nullptr; - String next_filename = (next != nullptr) ? String (uri_construct - (track_get_filename (next), cue_filename)) : String (); - bool last_track = (! next_filename || strcmp (next_filename, filename)); + const char * next_name = next ? track_get_filename (next) : nullptr; - Tuple tuple = base_tuple.ref (); - tuple.set_filename (filename); - tuple.set_int (Tuple::Track, track); + new_file = (! next_name || strcmp (next_name, cur_name)); - int begin = (int64_t) track_get_start (current) * 1000 / 75; - tuple.set_int (Tuple::StartTime, begin); - - if (last_track) - { - if (base_tuple.get_value_type (Tuple::Length) == Tuple::Int) - tuple.set_int (Tuple::Length, base_tuple.get_int (Tuple::Length) - begin); - } - else + if (base_tuple) { - int length = (int64_t) track_get_length (current) * 1000 / 75; - tuple.set_int (Tuple::Length, length); - tuple.set_int (Tuple::EndTime, begin + length); + Tuple tuple = base_tuple.ref (); + tuple.set_filename (filename); + tuple.set_int (Tuple::Track, track); + + int begin = (int64_t) track_get_start (cur) * 1000 / 75; + tuple.set_int (Tuple::StartTime, begin); + + if (new_file) + { + int length = base_tuple.get_int (Tuple::Length); + if (length > 0) + tuple.set_int (Tuple::Length, length - begin); + } + else + { + int length = (int64_t) track_get_length (cur) * 1000 / 75; + tuple.set_int (Tuple::Length, length); + tuple.set_int (Tuple::EndTime, begin + length); + } + + Cdtext * cdtext = track_get_cdtext (cur); + + if (cdtext) + { + const char * s; + if ((s = cdtext_get (PTI_PERFORMER, cdtext))) + tuple.set_str (Tuple::Artist, s); + if ((s = cdtext_get (PTI_TITLE, cdtext))) + tuple.set_str (Tuple::Title, s); + } + + items.append (String (filename), std::move (tuple), decoder); } - for (auto & pti : pti_map) - tuple_attach_cdtext (tuple, current, pti.field, pti.pti); - - items.append (filename, std::move (tuple)); - - current = next; - filename = next_filename; + if (! next_name) + break; - if (last_track) - { - base_tuple = Tuple (); - base_tuple_scanned = false; - } + cur = next; + cur_name = next_name; } return true; diff --git a/src/delete-files/delete-files.cc b/src/delete-files/delete-files.cc index 92fe939..7b9994e 100644 --- a/src/delete-files/delete-files.cc +++ b/src/delete-files/delete-files.cc @@ -26,6 +26,7 @@ #include <glib/gstdio.h> #include <gtk/gtk.h> +#define AUD_PLUGIN_GLIB_ONLY #include <libaudcore/audstrings.h> #include <libaudcore/i18n.h> #include <libaudcore/interface.h> @@ -86,7 +87,7 @@ static void really_delete (const char * filename) aud_ui_show_error (str_printf (_("Error deleting %s: %s."), filename, strerror (errno))); } -static void confirm_delete (void) +static void confirm_delete () { Index<String> files; @@ -118,7 +119,7 @@ static void confirm_delete (void) } } -static void start_delete (void) +static void start_delete () { if (dialog) { @@ -154,7 +155,7 @@ const char * const DeleteFiles::defaults[] = { "use_trash", "TRUE", nullptr}; -bool DeleteFiles::init (void) +bool DeleteFiles::init () { #if ! GLIB_CHECK_VERSION (2, 36, 0) g_type_init (); @@ -165,10 +166,10 @@ bool DeleteFiles::init (void) for (AudMenuID menu : menus) aud_plugin_menu_add (menu, start_delete, _("Delete Selected Files"), "edit-delete"); - return TRUE; + return true; } -void DeleteFiles::cleanup (void) +void DeleteFiles::cleanup () { if (dialog) gtk_widget_destroy (dialog); diff --git a/src/ffaudio/ffaudio-core.cc b/src/ffaudio/ffaudio-core.cc index de241df..ab954d9 100644 --- a/src/ffaudio/ffaudio-core.cc +++ b/src/ffaudio/ffaudio-core.cc @@ -374,7 +374,7 @@ Tuple FFaudio::read_tuple (const char * filename, VFSFile & file) } if (tuple && ! file.fseek (0, VFS_SEEK_SET)) - audtag::tuple_read (tuple, file); + audtag::read_tag (file, & tuple, nullptr); return tuple; } diff --git a/src/filewriter/filewriter.cc b/src/filewriter/filewriter.cc index c2c2a9a..7853e04 100644 --- a/src/filewriter/filewriter.cc +++ b/src/filewriter/filewriter.cc @@ -30,7 +30,6 @@ #include <libaudcore/runtime.h> #include "filewriter.h" -#include "plugins.h" #include "convert.h" class FileWriter : public OutputPlugin @@ -51,7 +50,6 @@ public: constexpr FileWriter () : OutputPlugin (info, 0, true) {} bool init (); - void cleanup (); StereoVolume get_volume () { return {0, 0}; } void set_volume (StereoVolume v) {} @@ -73,13 +71,23 @@ public: EXPORT FileWriter aud_plugin_instance; +enum { + FILENAME_ORIGINAL, + FILENAME_ORIGINAL_NO_SUFFIX, + FILENAME_FROM_TAG +}; + +/* really a boolean, but stored here as an integer + * since WidgetRadio supports only integer settings */ +static int save_original; + +/* stored as two separate booleans in the config file */ +static int filename_mode; + static String in_filename; static Tuple in_tuple; -struct format_info input; - -static GtkWidget * path_hbox, * path_dirbrowser; -static GtkWidget * fileext_combo, * plugin_button; +static GtkWidget * path_dirbrowser; enum fileext_t { @@ -96,36 +104,21 @@ enum fileext_t FILEEXT_MAX }; -static int fileext; static const char *fileext_str[FILEEXT_MAX] = { - "wav", + ".wav", #ifdef FILEWRITER_MP3 - "mp3", + ".mp3", #endif #ifdef FILEWRITER_VORBIS - "ogg", + ".ogg", #endif #ifdef FILEWRITER_FLAC - "flac" + ".flac" #endif }; static FileWriterImpl *plugin; - -static gboolean save_original; - -static GtkWidget *filenamefrom_hbox, *filenamefrom_label; -static gboolean filenamefromtags; - -static GtkWidget *use_suffix_toggle = nullptr; -static gboolean use_suffix; - -static GtkWidget *prependnumber_toggle; -static gboolean prependnumber; - -static String file_path; - static VFSFile output_file; FileWriterImpl *plugins[FILEEXT_MAX] = { @@ -141,19 +134,15 @@ FileWriterImpl *plugins[FILEEXT_MAX] = { #endif }; -static void set_plugin(void) -{ - if (fileext < 0 || fileext >= FILEEXT_MAX) - fileext = 0; - - plugin = plugins[fileext]; -} - const char * const FileWriter::defaults[] = { - "fileext", "0", /* WAV */ +#ifdef FILEWRITER_MP3 + "fileext", aud::numeric_string<MP3>::str, +#else + "fileext", aud::numeric_string<WAV>::str, +#endif "filenamefromtags", "TRUE", "prependnumber", "FALSE", - "save_original", "TRUE", + "save_original", "FALSE", "use_suffix", "FALSE", nullptr}; @@ -161,29 +150,28 @@ bool FileWriter::init () { aud_config_set_defaults ("filewriter", defaults); - fileext = aud_get_int ("filewriter", "fileext"); - filenamefromtags = aud_get_bool ("filewriter", "filenamefromtags"); - file_path = aud_get_str ("filewriter", "file_path"); - prependnumber = aud_get_bool ("filewriter", "prependnumber"); save_original = aud_get_bool ("filewriter", "save_original"); - use_suffix = aud_get_bool ("filewriter", "use_suffix"); - if (! file_path[0]) + if (aud_get_bool ("filewriter", "filenamefromtags")) + filename_mode = FILENAME_FROM_TAG; + else if (aud_get_bool ("filewriter", "use_suffix")) + filename_mode = FILENAME_ORIGINAL; + else + filename_mode = FILENAME_ORIGINAL_NO_SUFFIX; + + for (auto p : plugins) { - file_path = String (filename_to_uri (g_get_home_dir ())); - g_return_val_if_fail (file_path != nullptr, false); + if (p->init) + p->init (); } - set_plugin(); - if (plugin->init) - plugin->init(); - return true; } -void FileWriter::cleanup () +static StringBuf get_file_path () { - file_path = String (); + String path = aud_get_str ("filewriter", "file_path"); + return path[0] ? str_copy (path) : filename_to_uri (g_get_home_dir ()); } static VFSFile safe_create (const char * filename) @@ -212,70 +200,92 @@ void FileWriter::set_info (const char * filename, const Tuple & tuple) in_tuple = tuple.ref (); } -bool FileWriter::open_audio (int fmt, int rate, int nch) +static StringBuf format_filename (const char * suffix) { - String filename, directory; + const char * slash = in_filename ? strrchr (in_filename, '/') : nullptr; + const char * base = slash ? slash + 1 : nullptr; - input.format = fmt; - input.frequency = rate; - input.channels = nch; + StringBuf filename; - if (filenamefromtags) + if (save_original) { - String title = in_tuple.get_str (Tuple::FormattedTitle); - StringBuf buf = str_encode_percent (title); - str_replace_char (buf, '/', '-'); - filename = String (buf); + g_return_val_if_fail (base, StringBuf ()); + filename.insert (0, in_filename, base - in_filename); } else { - const char * original = strrchr (in_filename, '/'); - g_return_val_if_fail (original != nullptr, 0); - filename = String (original + 1); - - if (! use_suffix) - { - const char * temp; - if ((temp = strrchr (filename, '.'))) - filename = String (str_copy (filename, temp - filename)); - } + filename.steal (get_file_path ()); + if (filename[filename.len () - 1] != '/') + filename.insert (-1, "/"); } - if (prependnumber) + if (aud_get_bool ("filewriter", "prependnumber")) { int number = in_tuple.get_int (Tuple::Track); if (number >= 0) - filename = String (str_printf ("%d%%20%s", number, (const char *) filename)); + filename.combine (str_printf ("%d%%20", number)); } - if (save_original) + if (aud_get_bool ("filewriter", "filenamefromtags")) { - const char * temp = strrchr (in_filename, '/'); - g_return_val_if_fail (temp != nullptr, 0); - directory = String (str_copy (in_filename, temp + 1 - in_filename)); + String title = in_tuple.get_str (Tuple::FormattedTitle); + + /* truncate title at 200 bytes to avoid hitting filesystem limits */ + int len = aud::min ((int) strlen (title), 200); + + /* prevent truncation in middle of UTF-8 character */ + while ((title[len] & 0xc0) == 0x80) + len ++; + + StringBuf buf = str_copy (title, len); + + /* replace non-portable characters */ + const char * reserved = "<>:\"/\\|?*"; + for (char * c = buf; * c; c ++) + { + if (strchr (reserved, * c)) + * c = ' '; + } + + /* URI-encode */ + buf.steal (str_encode_percent (buf)); + filename.combine (std::move (buf)); } else { - g_return_val_if_fail (file_path[0], 0); - if (file_path[strlen (file_path) - 1] == '/') - directory = String (file_path); - else - directory = String (str_concat ({file_path, "/"})); + g_return_val_if_fail (base, StringBuf ()); + + const char * end = nullptr; + if (! aud_get_bool ("filewriter", "use_suffix")) + end = strrchr (base, '.'); + + filename.insert (-1, base, end ? end - base : -1); } - filename = String (str_printf ("%s%s.%s", (const char *) directory, - (const char *) filename, fileext_str[fileext])); + filename.insert (-1, suffix); + return filename; +} - output_file = safe_create (filename); - if (! output_file) - goto err; +bool FileWriter::open_audio (int fmt, int rate, int nch) +{ + int ext = aud_get_int ("filewriter", "fileext"); + g_return_val_if_fail (ext >= 0 && ext < FILEEXT_MAX, false); + + StringBuf filename = format_filename (fileext_str[ext]); + if (! filename) + return false; + + plugin = plugins[ext]; - convert_init (fmt, plugin->format_required (fmt)); + int out_fmt = plugin->format_required (fmt); + convert_init (fmt, out_fmt); - if (plugin->open (output_file, input, in_tuple)) + output_file = safe_create (filename); + if (output_file && plugin->open (output_file, {out_fmt, rate, nch}, in_tuple)) return true; -err: + plugin = nullptr; + output_file = VFSFile (); in_filename = String (); in_tuple = Tuple (); return false; @@ -294,214 +304,124 @@ void FileWriter::close_audio () plugin->close (output_file); convert_free (); + plugin = nullptr; output_file = VFSFile (); in_filename = String (); in_tuple = Tuple (); } -static void configure_response_cb (void) -{ - fileext = gtk_combo_box_get_active(GTK_COMBO_BOX(fileext_combo)); - - char * temp = gtk_file_chooser_get_uri ((GtkFileChooser *) path_dirbrowser); - file_path = String (temp); - g_free (temp); - - use_suffix = - gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(use_suffix_toggle)); - - prependnumber = - gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(prependnumber_toggle)); - - aud_set_int ("filewriter", "fileext", fileext); - aud_set_bool ("filewriter", "filenamefromtags", filenamefromtags); - aud_set_str ("filewriter", "file_path", file_path); - aud_set_bool ("filewriter", "prependnumber", prependnumber); - aud_set_bool ("filewriter", "save_original", save_original); - aud_set_bool ("filewriter", "use_suffix", use_suffix); -} - -static void fileext_cb(GtkWidget *combo, void * data) -{ - fileext = gtk_combo_box_get_active(GTK_COMBO_BOX(fileext_combo)); - set_plugin(); - if (plugin->init) - plugin->init(); - - gtk_widget_set_sensitive(plugin_button, plugin->configure != nullptr); -} - -static void plugin_configure_cb(GtkWidget *button, void * data) +static void * create_dirbrowser () { - if (plugin->configure) - plugin->configure(); -} - + path_dirbrowser = gtk_file_chooser_button_new (_("Pick a folder"), + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER); + gtk_file_chooser_set_uri ((GtkFileChooser *) path_dirbrowser, get_file_path ()); + gtk_widget_set_sensitive (path_dirbrowser, ! save_original); -static void saveplace_original_cb(GtkWidget *button, void * data) -{ - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button))) + auto set_cb = [] () { - gtk_widget_set_sensitive(path_hbox, FALSE); - save_original = TRUE; - } -} + char * uri = gtk_file_chooser_get_uri ((GtkFileChooser *) path_dirbrowser); + aud_set_str ("filewriter", "file_path", uri); + g_free (uri); + }; -static void saveplace_custom_cb(GtkWidget *button, void * data) -{ - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button))) - { - gtk_widget_set_sensitive(path_hbox, TRUE); - save_original = FALSE; - } -} + // "file-set" is unreliable, so get the path on "destroy" as well + g_signal_connect (path_dirbrowser, "file-set", set_cb, nullptr); + g_signal_connect (path_dirbrowser, "destroy", set_cb, nullptr); -static void filenamefromtags_cb(GtkWidget *button, void * data) -{ - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button))) - { - gtk_widget_set_sensitive(use_suffix_toggle, FALSE); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(use_suffix_toggle), FALSE); - use_suffix = FALSE; - filenamefromtags = TRUE; - } + return path_dirbrowser; } -static void filenamefromfilename_cb(GtkWidget *button, void * data) +static void save_original_cb () { - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button))) - { - gtk_widget_set_sensitive(use_suffix_toggle, TRUE); - filenamefromtags = FALSE; - } + aud_set_bool ("filewriter", "save_original", save_original); + gtk_widget_set_sensitive (path_dirbrowser, ! save_original); } -static void * file_configure (void) +static void filename_mode_cb () { - GtkWidget * configure_vbox = gtk_vbox_new (FALSE, 6); - - GtkWidget * fileext_hbox = gtk_hbox_new (FALSE, 5); - gtk_box_pack_start(GTK_BOX(configure_vbox), fileext_hbox, FALSE, FALSE, 0); + aud_set_bool ("filewriter", "filenamefromtags", (filename_mode == FILENAME_FROM_TAG)); + aud_set_bool ("filewriter", "use_suffix", (filename_mode == FILENAME_ORIGINAL)); +} - GtkWidget * fileext_label = gtk_label_new (_("Output file format:")); - gtk_box_pack_start(GTK_BOX(fileext_hbox), fileext_label, FALSE, FALSE, 0); +const char FileWriter::about[] = + N_("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.\n\n" + "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.\n\n" + "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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, " + "USA."); - fileext_combo = gtk_combo_box_text_new (); - gtk_combo_box_text_append_text ((GtkComboBoxText *) fileext_combo, "WAV"); +static const ComboItem plugin_combo[] = { + ComboItem ("WAV", WAV) #ifdef FILEWRITER_MP3 - gtk_combo_box_text_append_text ((GtkComboBoxText *) fileext_combo, "MP3"); + ,ComboItem ("MP3", MP3) #endif #ifdef FILEWRITER_VORBIS - gtk_combo_box_text_append_text ((GtkComboBoxText *) fileext_combo, "Vorbis"); + ,ComboItem ("Vorbis", VORBIS) #endif #ifdef FILEWRITER_FLAC - gtk_combo_box_text_append_text ((GtkComboBoxText *) fileext_combo, "FLAC"); + ,ComboItem ("FLAC", FLAC) #endif - gtk_box_pack_start(GTK_BOX(fileext_hbox), fileext_combo, FALSE, FALSE, 0); - gtk_combo_box_set_active(GTK_COMBO_BOX(fileext_combo), fileext); - - plugin_button = gtk_button_new_with_label(_("Configure")); - gtk_widget_set_sensitive(plugin_button, plugin->configure != nullptr); - gtk_box_pack_end(GTK_BOX(fileext_hbox), plugin_button, FALSE, FALSE, 0); - - gtk_box_pack_start(GTK_BOX(configure_vbox), gtk_hseparator_new(), FALSE, FALSE, 0); - - GtkWidget * saveplace_hbox = gtk_hbox_new (FALSE, 5); - gtk_container_add(GTK_CONTAINER(configure_vbox), saveplace_hbox); - - GtkWidget * saveplace1 = gtk_radio_button_new_with_label (nullptr, - _("Save into original directory")); - gtk_box_pack_start ((GtkBox *) saveplace_hbox, saveplace1, FALSE, FALSE, 0); - - GtkWidget * saveplace2 = gtk_radio_button_new_with_label_from_widget - ((GtkRadioButton *) saveplace1, _("Save into custom directory")); - - if (!save_original) - gtk_toggle_button_set_active ((GtkToggleButton *) saveplace2, TRUE); - - gtk_box_pack_start ((GtkBox *) saveplace_hbox, saveplace2, FALSE, FALSE, 0); - - path_hbox = gtk_hbox_new (FALSE, 5); - gtk_box_pack_start(GTK_BOX(configure_vbox), path_hbox, FALSE, FALSE, 0); - - GtkWidget * path_label = gtk_label_new (_("Output file folder:")); - gtk_box_pack_start ((GtkBox *) path_hbox, path_label, FALSE, FALSE, 0); - - path_dirbrowser = - gtk_file_chooser_button_new (_("Pick a folder"), - GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER); - gtk_file_chooser_set_uri ((GtkFileChooser *) path_dirbrowser, file_path); - gtk_box_pack_start(GTK_BOX(path_hbox), path_dirbrowser, TRUE, TRUE, 0); - - if (save_original) - gtk_widget_set_sensitive(path_hbox, FALSE); - - gtk_box_pack_start(GTK_BOX(configure_vbox), gtk_hseparator_new(), FALSE, FALSE, 0); - - filenamefrom_hbox = gtk_hbox_new (FALSE, 5); - gtk_container_add(GTK_CONTAINER(configure_vbox), filenamefrom_hbox); - - filenamefrom_label = gtk_label_new(_("Generate file name from:")); - gtk_box_pack_start(GTK_BOX(filenamefrom_hbox), filenamefrom_label, FALSE, FALSE, 0); - - GtkWidget * filenamefrom_toggle1 = gtk_radio_button_new_with_label - (nullptr, _("Original file tag")); - gtk_box_pack_start ((GtkBox *) filenamefrom_hbox, filenamefrom_toggle1, FALSE, FALSE, 0); - - GtkWidget * filenamefrom_toggle2 = - gtk_radio_button_new_with_label_from_widget - ((GtkRadioButton *) filenamefrom_toggle1, _("Original file name")); - gtk_box_pack_start ((GtkBox *) filenamefrom_hbox, filenamefrom_toggle2, FALSE, FALSE, 0); - - if (!filenamefromtags) - gtk_toggle_button_set_active ((GtkToggleButton *) filenamefrom_toggle2, TRUE); - - use_suffix_toggle = gtk_check_button_new_with_label(_("Include original file name extension")); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(use_suffix_toggle), use_suffix); - gtk_box_pack_start(GTK_BOX(configure_vbox), use_suffix_toggle, FALSE, FALSE, 0); - - if (filenamefromtags) - gtk_widget_set_sensitive(use_suffix_toggle, FALSE); - - gtk_box_pack_start(GTK_BOX(configure_vbox), gtk_hseparator_new(), FALSE, FALSE, 0); +}; - prependnumber_toggle = gtk_check_button_new_with_label(_("Prepend track number to file name")); - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(prependnumber_toggle), prependnumber); - gtk_box_pack_start(GTK_BOX(configure_vbox), prependnumber_toggle, FALSE, FALSE, 0); +static const PreferencesWidget main_widgets[] = { + WidgetCombo (N_("Output file format:"), + WidgetInt ("filewriter", "fileext"), + {{plugin_combo}}), + WidgetSeparator ({true}), + WidgetRadio (N_("Save into original directory"), + WidgetInt (save_original, save_original_cb), + {true}), + WidgetRadio (N_("Save into custom directory:"), + WidgetInt (save_original, save_original_cb), + {false}), + WidgetCustomGTK (create_dirbrowser), + WidgetSeparator ({true}), + WidgetLabel (N_("Generate file name from:")), + WidgetRadio (N_("Original file name"), + WidgetInt (filename_mode, filename_mode_cb), + {FILENAME_ORIGINAL}), + WidgetRadio (N_("Original file name (no suffix)"), + WidgetInt (filename_mode, filename_mode_cb), + {FILENAME_ORIGINAL_NO_SUFFIX}), + WidgetRadio (N_("Original file tag"), + WidgetInt (filename_mode, filename_mode_cb), + {FILENAME_FROM_TAG}), + WidgetSeparator ({true}), + WidgetCheck (N_("Prepend track number to file name"), + WidgetBool ("filewriter", "prependnumber")) +}; - g_signal_connect (fileext_combo, "changed", (GCallback) fileext_cb, nullptr); - g_signal_connect (plugin_button, "clicked", (GCallback) plugin_configure_cb, nullptr); - g_signal_connect (saveplace1, "toggled", (GCallback) saveplace_original_cb, nullptr); - g_signal_connect (saveplace2, "toggled", (GCallback) saveplace_custom_cb, nullptr); - g_signal_connect (filenamefrom_toggle1, "toggled", (GCallback) filenamefromtags_cb, nullptr); - g_signal_connect (filenamefrom_toggle2, "toggled", - (GCallback) filenamefromfilename_cb, nullptr); +#ifdef FILEWRITER_MP3 +static const PreferencesWidget mp3_widgets[] = { + WidgetCustomGTK (mp3_configure) +}; +#endif - return configure_vbox; -} +#ifdef FILEWRITER_VORBIS +static const PreferencesWidget vorbis_widgets[] = { + WidgetCustomGTK (vorbis_configure) +}; +#endif -const char FileWriter::about[] = - N_("This program is free software; you can redistribute it and/or modify\n" - "it under the terms of the GNU General Public License as published by\n" - "the Free Software Foundation; either version 2 of the License, or\n" - "(at your option) any later version.\n" - "\n" - "This program is distributed in the hope that it will be useful,\n" - "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" - "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" - "GNU General Public License for more details.\n" - "\n" - "You should have received a copy of the GNU General Public License\n" - "along with this program; if not, write to the Free Software\n" - "Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,\n" - "USA."); +static const NotebookTab tabs[] = { + {N_("General"), {main_widgets}} +#ifdef FILEWRITER_MP3 + ,{"MP3", {mp3_widgets}} +#endif +#ifdef FILEWRITER_VORBIS + ,{"Vorbis", {vorbis_widgets}} +#endif +}; const PreferencesWidget FileWriter::widgets[] = { - WidgetCustomGTK (file_configure) + WidgetNotebook ({{tabs}}) }; -const PluginPreferences FileWriter::prefs = { - {widgets}, - nullptr, // init - configure_response_cb -}; +const PluginPreferences FileWriter::prefs = {{widgets}}; diff --git a/src/filewriter/filewriter.h b/src/filewriter/filewriter.h index 4fe437b..e3ff449 100644 --- a/src/filewriter/filewriter.h +++ b/src/filewriter/filewriter.h @@ -37,11 +37,26 @@ struct format_info { struct FileWriterImpl { void (* init) (); - void (* configure) (); bool (* open) (VFSFile & file, const format_info & info, const Tuple & tuple); void (* write) (VFSFile & file, const void * data, int length); void (* close) (VFSFile & file); int (* format_required) (int fmt); }; +extern FileWriterImpl wav_plugin; + +#ifdef FILEWRITER_MP3 +extern FileWriterImpl mp3_plugin; +void * mp3_configure (); +#endif + +#ifdef FILEWRITER_VORBIS +extern FileWriterImpl vorbis_plugin; +void * vorbis_configure (); +#endif + +#ifdef FILEWRITER_FLAC +extern FileWriterImpl flac_plugin; +#endif + #endif diff --git a/src/filewriter/flac.cc b/src/filewriter/flac.cc index 8ea22f4..0283c46 100644 --- a/src/filewriter/flac.cc +++ b/src/filewriter/flac.cc @@ -19,7 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "plugins.h" +#include "filewriter.h" #ifdef FILEWRITER_FLAC @@ -196,7 +196,6 @@ static int flac_format_required (int fmt) FileWriterImpl flac_plugin = { nullptr, // init - nullptr, // configure flac_open, flac_write, flac_close, diff --git a/src/filewriter/mp3.cc b/src/filewriter/mp3.cc index 81f2aab..3c50153 100644 --- a/src/filewriter/mp3.cc +++ b/src/filewriter/mp3.cc @@ -22,7 +22,7 @@ /* #define AUD_DEBUG 1 */ -#include "plugins.h" +#include "filewriter.h" #ifdef FILEWRITER_MP3 @@ -35,16 +35,14 @@ #include <libaudcore/runtime.h> #define MODES 4 -enum {MODE_AUTO = 4, MODE_JOINT = 1, MODE_STEREO = 0, MODE_MONO = 3}; -static const int modes[MODES] = {MODE_AUTO, MODE_JOINT, MODE_STEREO, MODE_MONO}; +static const int modes[MODES] = {NOT_SET, JOINT_STEREO, STEREO, MONO}; static const char * const mode_names[MODES] = {N_("Auto"), N_("Joint Stereo"), N_("Stereo"), N_("Mono")}; -static GtkWidget *configure_win = nullptr; static GtkWidget *alg_quality_spin; static GtkWidget *alg_quality_hbox; static GtkAdjustment * alg_quality_adj; -static GtkWidget *vbox, *notebook; +static GtkWidget *notebook; static GtkWidget *quality_vbox, *quality_hbox1, *alg_quality_frame; static GtkWidget *enc_quality_frame, *enc_quality_label1, *enc_quality_label2; static GtkWidget * enc_radio1, * enc_radio2; @@ -121,43 +119,19 @@ static const char * const mp3_defaults[] = { "bitrate_val", "128", "compression_val", "11", "enc_toggle_val", "0", - "audio_mode_val", "4", /* MODE_AUTO */ + "audio_mode_val", aud::numeric_string<NOT_SET>::str, "enforce_iso_val", "0", "error_protect_val", "0", nullptr}; -static int vbr_on, vbr_type, vbr_min_val, vbr_max_val, enforce_min_val, - vbr_quality_val, abr_val, toggle_xing_val, mark_original_val, - mark_copyright_val, force_v2_val, only_v1_val, only_v2_val, algo_quality_val, - out_samplerate_val, bitrate_val; -static float compression_val; -static int enc_toggle_val, audio_mode_val, enforce_iso_val, error_protect_val; +#define GET_INT(n) aud_get_int("filewriter_mp3", n) +#define SET_INT(n, v) aud_set_int("filewriter_mp3", n, v) +#define GET_DOUBLE(n) aud_get_double("filewriter_mp3", n) +#define SET_DOUBLE(n, v) aud_set_double("filewriter_mp3", n, v) static void mp3_init () { aud_config_set_defaults ("filewriter_mp3", mp3_defaults); - - vbr_on = aud_get_int ("filewriter_mp3", "vbr_on"); - vbr_type = aud_get_int ("filewriter_mp3", "vbr_type"); - vbr_min_val = aud_get_int ("filewriter_mp3", "vbr_min_val"); - vbr_max_val = aud_get_int ("filewriter_mp3", "vbr_max_val"); - enforce_min_val = aud_get_int ("filewriter_mp3", "enforce_min_val"); - vbr_quality_val = aud_get_int ("filewriter_mp3", "vbr_quality_val"); - abr_val = aud_get_int ("filewriter_mp3", "abr_val"); - toggle_xing_val = aud_get_int ("filewriter_mp3", "toggle_xing_val"); - mark_original_val = aud_get_int ("filewriter_mp3", "mark_original_val"); - mark_copyright_val = aud_get_int ("filewriter_mp3", "mark_copyright_val"); - force_v2_val = aud_get_int ("filewriter_mp3", "force_v2_val"); - only_v1_val = aud_get_int ("filewriter_mp3", "only_v1_val"); - only_v2_val = aud_get_int ("filewriter_mp3", "only_v2_val"); - algo_quality_val = aud_get_int ("filewriter_mp3", "algo_quality_val"); - out_samplerate_val = aud_get_int ("filewriter_mp3", "out_samplerate_val"); - bitrate_val = aud_get_int ("filewriter_mp3", "bitrate_val"); - compression_val = aud_get_double ("filewriter_mp3", "compression_val"); - enc_toggle_val = aud_get_int ("filewriter_mp3", "enc_toggle_val"); - audio_mode_val = aud_get_int ("filewriter_mp3", "audio_mode_val"); - enforce_iso_val = aud_get_int ("filewriter_mp3", "enforce_iso_val"); - error_protect_val = aud_get_int ("filewriter_mp3", "error_protect_val"); } static bool mp3_open (VFSFile & file, const format_info & info, const Tuple & tuple) @@ -190,26 +164,26 @@ static bool mp3_open (VFSFile & file, const format_info & info, const Tuple & tu lameid3.track_number = String (int_to_str (tuple.get_int (Tuple::Track))); id3tag_set_track(gfp, lameid3.track_number); - if (force_v2_val) + if (GET_INT("force_v2_val")) id3tag_add_v2(gfp); - if (only_v1_val) + if (GET_INT("only_v1_val")) id3tag_v1_only(gfp); - if (only_v2_val) + if (GET_INT("only_v2_val")) id3tag_v2_only(gfp); /* input stream description */ lame_set_in_samplerate(gfp, info.frequency); lame_set_num_channels(gfp, info.channels); - /* Maybe implement this? */ - /* lame_set_scale(lame_global_flags *, float); */ - lame_set_out_samplerate(gfp, out_samplerate_val); + lame_set_out_samplerate(gfp, GET_INT("out_samplerate_val")); /* general control parameters */ - lame_set_bWriteVbrTag(gfp, toggle_xing_val); - lame_set_quality(gfp, algo_quality_val); - if (audio_mode_val != 4) { + lame_set_bWriteVbrTag(gfp, GET_INT("toggle_xing_val")); + lame_set_quality(gfp, GET_INT("algo_quality_val")); + + const int audio_mode_val = GET_INT("audio_mode_val"); + if (audio_mode_val != NOT_SET) { AUDDBG("set mode to %d\n", audio_mode_val); lame_set_mode(gfp, (MPEG_mode) audio_mode_val); } @@ -218,28 +192,33 @@ static bool mp3_open (VFSFile & file, const format_info & info, const Tuple & tu lame_set_debugf(gfp, lame_debugf); lame_set_msgf(gfp, lame_debugf); - if (enc_toggle_val == 0 && vbr_on == 0) - lame_set_brate(gfp, bitrate_val); + const int vbr_on = GET_INT("vbr_on"); + if (GET_INT("enc_toggle_val") == 0 && vbr_on == 0) + lame_set_brate(gfp, GET_INT("bitrate_val")); else if (vbr_on == 0) - lame_set_compression_ratio(gfp, compression_val); + lame_set_compression_ratio(gfp, GET_DOUBLE("compression_val")); /* frame params */ - lame_set_copyright(gfp, mark_copyright_val); - lame_set_original(gfp, mark_original_val); - lame_set_error_protection(gfp, error_protect_val); - lame_set_strict_ISO(gfp, enforce_iso_val); + lame_set_copyright(gfp, GET_INT("mark_copyright_val")); + lame_set_original(gfp, GET_INT("mark_original_val")); + lame_set_error_protection(gfp, GET_INT("error_protect_val")); + lame_set_strict_ISO(gfp, GET_INT("enforce_iso_val")); if (vbr_on != 0) { - if (vbr_type == 0) - lame_set_VBR(gfp, (vbr_mode) 2); + const int vbr_min_val = GET_INT("vbr_min_val"); + const int vbr_max_val = GET_INT("vbr_max_val"); + + if (GET_INT("vbr_type") == 0) + lame_set_VBR(gfp, vbr_rh); else - lame_set_VBR(gfp, (vbr_mode) 3); - lame_set_VBR_q(gfp, vbr_quality_val); - lame_set_VBR_mean_bitrate_kbps(gfp, abr_val); + lame_set_VBR(gfp, vbr_abr); + + lame_set_VBR_q(gfp, GET_INT("vbr_quality_val")); + lame_set_VBR_mean_bitrate_kbps(gfp, GET_INT("abr_val")); lame_set_VBR_min_bitrate_kbps(gfp, vbr_min_val); - lame_set_VBR_max_bitrate_kbps(gfp, vbr_max_val); - lame_set_VBR_hard_min(gfp, enforce_min_val); + lame_set_VBR_max_bitrate_kbps(gfp, aud::max(vbr_min_val, vbr_max_val)); + lame_set_VBR_hard_min(gfp, GET_INT("enforce_min_val")); } /* not to write id3 tag automatically. */ @@ -274,11 +253,13 @@ static void mp3_write (VFSFile & file, const void * data, int length) while (1) { if (channels == 1) - encoded = lame_encode_buffer (gfp, (int16_t *) data, (int16_t *) data, - length / 2, write_buffer.begin (), write_buffer.len ()); + encoded = lame_encode_buffer_ieee_float (gfp, (const float *) data, + (const float *) data, length / sizeof (float), + write_buffer.begin (), write_buffer.len ()); else - encoded = lame_encode_buffer_interleaved (gfp, (int16_t *) data, - length / 4, write_buffer.begin (), write_buffer.len ()); + encoded = lame_encode_buffer_interleaved_ieee_float (gfp, + (const float *) data, length / (2 * sizeof (float)), + write_buffer.begin (), write_buffer.len ()); if (encoded != -1) break; @@ -346,10 +327,8 @@ static void mp3_close (VFSFile & file) static void algo_qual(GtkAdjustment * adjustment, void * user_data) { - - algo_quality_val = - gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON - (alg_quality_spin)); + SET_INT("algo_quality_val", + gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(alg_quality_spin))); } @@ -358,9 +337,9 @@ static void samplerate_changed (GtkComboBox * combo) int i = gtk_combo_box_get_active (combo) - 1; if (i >= 0 && i < aud::n_elems (available_samplerates)) - out_samplerate_val = available_samplerates[i]; + SET_INT("out_samplerate_val", available_samplerates[i]); else - out_samplerate_val = 0; + SET_INT("out_samplerate_val", 0); } static void bitrate_changed (GtkComboBox * combo) @@ -368,24 +347,22 @@ static void bitrate_changed (GtkComboBox * combo) int i = gtk_combo_box_get_active (combo); if (i >= 0 && i < aud::n_elems (available_bitrates)) - bitrate_val = available_bitrates[i]; + SET_INT("bitrate_val", available_bitrates[i]); else - bitrate_val = 128; + SET_INT("bitrate_val", 128); } static void compression_change(GtkAdjustment * adjustment, void * user_data) { - compression_val = gtk_spin_button_get_value ((GtkSpinButton *) - compression_spin); + SET_DOUBLE("compression_val", + gtk_spin_button_get_value(GTK_SPIN_BUTTON(compression_spin))); } static void encoding_toggle(GtkToggleButton * togglebutton, void * user_data) { - - enc_toggle_val = GPOINTER_TO_INT(user_data); - + SET_INT("enc_toggle_val", GPOINTER_TO_INT(user_data)); } static void mode_changed (GtkComboBox * combo) @@ -393,61 +370,55 @@ static void mode_changed (GtkComboBox * combo) int i = gtk_combo_box_get_active (combo); if (i >= 0 && i < MODES) - audio_mode_val = modes[i]; + SET_INT("audio_mode_val", modes[i]); else - audio_mode_val = MODE_AUTO; + SET_INT("audio_mode_val", NOT_SET); } static void toggle_enforce_iso(GtkToggleButton * togglebutton, void * user_data) { - - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(enforce_iso_toggle)) - == TRUE) - enforce_iso_val = 1; + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(enforce_iso_toggle))) + SET_INT("enforce_iso_val", 1); else - enforce_iso_val = 0; - + SET_INT("enforce_iso_val", 0); } static void toggle_error_protect(GtkToggleButton * togglebutton, void * user_data) { - - if (gtk_toggle_button_get_active - (GTK_TOGGLE_BUTTON(error_protection_toggle)) == TRUE) - error_protect_val = 1; + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(error_protection_toggle))) + SET_INT("error_protect_val", 1); else - error_protect_val = 0; - + SET_INT("error_protect_val", 0); } static void toggle_vbr(GtkToggleButton * togglebutton, void * user_data) { if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(vbr_toggle)) == - TRUE) { - gtk_widget_set_sensitive(vbr_options_vbox, TRUE); - gtk_widget_set_sensitive(enc_quality_frame, FALSE); - vbr_on = 1; + true) { + gtk_widget_set_sensitive(vbr_options_vbox, true); + gtk_widget_set_sensitive(enc_quality_frame, false); + SET_INT("vbr_on", 1); - if (vbr_type == 0) { + if (GET_INT("vbr_type") == 0) { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON - (vbr_type_radio1), TRUE); - gtk_widget_set_sensitive(abr_frame, FALSE); - gtk_widget_set_sensitive(vbr_frame, TRUE); + (vbr_type_radio1), true); + gtk_widget_set_sensitive(abr_frame, false); + gtk_widget_set_sensitive(vbr_frame, true); } - else if (vbr_type == 1) { + else { gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON - (vbr_type_radio2), TRUE); - gtk_widget_set_sensitive(abr_frame, TRUE); - gtk_widget_set_sensitive(vbr_frame, FALSE); + (vbr_type_radio2), true); + gtk_widget_set_sensitive(abr_frame, true); + gtk_widget_set_sensitive(vbr_frame, false); } } else { - gtk_widget_set_sensitive(vbr_options_vbox, FALSE); - gtk_widget_set_sensitive(enc_quality_frame, TRUE); - vbr_on = 0; + gtk_widget_set_sensitive(vbr_options_vbox, false); + gtk_widget_set_sensitive(enc_quality_frame, true); + SET_INT("vbr_on", 0); } } @@ -455,14 +426,14 @@ static void vbr_abr_toggle(GtkToggleButton * togglebutton, void * user_data) { if (!strcmp((char *) user_data, "VBR")) { - gtk_widget_set_sensitive(abr_frame, FALSE); - gtk_widget_set_sensitive(vbr_frame, TRUE); - vbr_type = 0; + gtk_widget_set_sensitive(abr_frame, false); + gtk_widget_set_sensitive(vbr_frame, true); + SET_INT("vbr_type", 0); } else if (!strcmp((char *) user_data, "ABR")) { - gtk_widget_set_sensitive(abr_frame, TRUE); - gtk_widget_set_sensitive(vbr_frame, FALSE); - vbr_type = 1; + gtk_widget_set_sensitive(abr_frame, true); + gtk_widget_set_sensitive(vbr_frame, false); + SET_INT("vbr_type", 1); } } @@ -471,9 +442,9 @@ static void vbr_min_changed (GtkComboBox * combo) int i = gtk_combo_box_get_active (combo); if (i >= 0 && i < aud::n_elems (available_bitrates)) - vbr_min_val = available_bitrates[i]; + SET_INT("vbr_min_val", available_bitrates[i]); else - vbr_min_val = 32; + SET_INT("vbr_min_val", 32); } static void vbr_max_changed (GtkComboBox * combo) @@ -481,30 +452,24 @@ static void vbr_max_changed (GtkComboBox * combo) int i = gtk_combo_box_get_active (combo); if (i >= 0 && i < aud::n_elems (available_bitrates)) - vbr_max_val = available_bitrates[i]; + SET_INT("vbr_max_val", available_bitrates[i]); else - vbr_max_val = 320; + SET_INT("vbr_max_val", 320); } static void toggle_enforce_min(GtkToggleButton * togglebutton, void * user_data) { - - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(enforce_min_toggle)) - == TRUE) - enforce_min_val = 1; + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(enforce_min_toggle))) + SET_INT("enforce_min_val", 1); else - enforce_min_val = 0; - + SET_INT("enforce_min_val", 0); } static void vbr_qual(GtkAdjustment * adjustment, void * user_data) { - - vbr_quality_val = - gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON - (vbr_quality_spin)); - + SET_INT("vbr_quality_val", + gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(vbr_quality_spin))); } static void abr_changed (GtkComboBox * combo) @@ -512,63 +477,52 @@ static void abr_changed (GtkComboBox * combo) int i = gtk_combo_box_get_active (combo); if (i >= 0 && i < aud::n_elems (available_bitrates)) - abr_val = available_bitrates[i]; + SET_INT("abr_val", available_bitrates[i]); else - abr_val = 128; + SET_INT("abr_val", 128); } static void toggle_xing(GtkToggleButton * togglebutton, void * user_data) { - - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(xing_header_toggle)) == TRUE) - toggle_xing_val = 0; + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(xing_header_toggle))) + SET_INT("toggle_xing_val", 0); else - toggle_xing_val = 1; - + SET_INT("toggle_xing_val", 1); } static void toggle_original(GtkToggleButton * togglebutton, void * user_data) { - - if (gtk_toggle_button_get_active - (GTK_TOGGLE_BUTTON(tags_original_toggle)) == TRUE) - mark_original_val = 1; + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tags_original_toggle))) + SET_INT("mark_original_val", 1); else - mark_original_val = 0; - + SET_INT("mark_original_val", 0); } static void toggle_copyright(GtkToggleButton * togglebutton, void * user_data) { - - if (gtk_toggle_button_get_active - (GTK_TOGGLE_BUTTON(tags_copyright_toggle)) == TRUE) - mark_copyright_val = 1; + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tags_copyright_toggle))) + SET_INT("mark_copyright_val", 1); else - mark_copyright_val = 0; - + SET_INT("mark_copyright_val", 0); } static void force_v2_toggle(GtkToggleButton * togglebutton, void * user_data) { - if (gtk_toggle_button_get_active - (GTK_TOGGLE_BUTTON(tags_force_id3v2_toggle)) == TRUE) { - force_v2_val = 1; - if (gtk_toggle_button_get_active - (GTK_TOGGLE_BUTTON(tags_only_v1_toggle)) == TRUE) { + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tags_force_id3v2_toggle))) { + SET_INT("force_v2_val", 1); + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tags_only_v1_toggle))) { inside = 1; - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON - (tags_only_v1_toggle), FALSE); - only_v1_val = 0; + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tags_only_v1_toggle), false); + SET_INT("only_v1_val", 0); inside = 0; } } else - force_v2_val = 0; + SET_INT("force_v2_val", 0); } @@ -576,145 +530,79 @@ static void id3_only_version(GtkToggleButton * togglebutton, void * user_data) { if (!strcmp((char *) user_data, "v1") && inside != 1) { - if (gtk_toggle_button_get_active - (GTK_TOGGLE_BUTTON(tags_only_v1_toggle)) == TRUE) + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tags_only_v1_toggle))) { inside = 1; - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON - (tags_only_v2_toggle), FALSE); - only_v1_val = 1; - only_v2_val = 0; - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON - (tags_force_id3v2_toggle), FALSE); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tags_only_v2_toggle), false); + SET_INT("only_v1_val", 1); + SET_INT("only_v2_val", 0); + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tags_force_id3v2_toggle), false); inside = 0; } } else if (!strcmp((char *) user_data, "v2") && inside != 1) { - if (gtk_toggle_button_get_active - (GTK_TOGGLE_BUTTON(tags_only_v2_toggle)) == TRUE) + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tags_only_v2_toggle))) { inside = 1; - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON - (tags_only_v1_toggle), FALSE); - only_v1_val = 0; - only_v2_val = 1; + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(tags_only_v1_toggle), false); + SET_INT("only_v1_val", 0); + SET_INT("only_v2_val", 1); inside = 0; } } } - - -/* Save Configuration */ - -static void configure_response_cb (GtkWidget * window, int response) -{ - if (response != GTK_RESPONSE_OK) - { - gtk_widget_destroy (window); - return; - } - - if (vbr_min_val > vbr_max_val) - vbr_max_val = vbr_min_val; - - aud_set_int ("filewriter_mp3", "vbr_on", vbr_on); - aud_set_int ("filewriter_mp3", "vbr_type", vbr_type); - aud_set_int ("filewriter_mp3", "vbr_min_val", vbr_min_val); - aud_set_int ("filewriter_mp3", "vbr_max_val", vbr_max_val); - aud_set_int ("filewriter_mp3", "enforce_min_val", enforce_min_val); - aud_set_int ("filewriter_mp3", "vbr_quality_val", vbr_quality_val); - aud_set_int ("filewriter_mp3", "abr_val", abr_val); - aud_set_int ("filewriter_mp3", "toggle_xing_val", toggle_xing_val); - aud_set_int ("filewriter_mp3", "mark_original_val", mark_original_val); - aud_set_int ("filewriter_mp3", "mark_copyright_val", mark_copyright_val); - aud_set_int ("filewriter_mp3", "force_v2_val", force_v2_val); - aud_set_int ("filewriter_mp3", "only_v1_val", only_v1_val); - aud_set_int ("filewriter_mp3", "only_v2_val", only_v2_val); - aud_set_int ("filewriter_mp3", "algo_quality_val", algo_quality_val); - aud_set_int ("filewriter_mp3", "out_samplerate_val", out_samplerate_val); - aud_set_int ("filewriter_mp3", "bitrate_val", bitrate_val); - aud_set_double ("filewriter_mp3", "compression_val", compression_val); - aud_set_int ("filewriter_mp3", "enc_toggle_val", enc_toggle_val); - aud_set_int ("filewriter_mp3", "audio_mode_val", audio_mode_val); - aud_set_int ("filewriter_mp3", "enforce_iso_val", enforce_iso_val); - aud_set_int ("filewriter_mp3", "error_protect_val", error_protect_val); - - gtk_widget_destroy (window); -} - - /************************/ /* Configuration Widget */ /************************/ - -static void mp3_configure(void) +void * mp3_configure () { - if (! configure_win) - { - configure_win = gtk_dialog_new_with_buttons (_("MP3 Configuration"), - nullptr, (GtkDialogFlags) 0, _("_Cancel"), GTK_RESPONSE_CANCEL, _("_OK"), - GTK_RESPONSE_OK, nullptr); - - g_signal_connect (configure_win, "response", (GCallback) configure_response_cb, nullptr); - g_signal_connect (configure_win, "destroy", (GCallback) - gtk_widget_destroyed, & configure_win); - - vbox = gtk_dialog_get_content_area ((GtkDialog *) configure_win); - notebook = gtk_notebook_new(); - gtk_box_pack_start(GTK_BOX(vbox), notebook, TRUE, TRUE, 0); /* Quality */ - quality_vbox = gtk_vbox_new (FALSE, 5); + quality_vbox = gtk_vbox_new (false, 5); gtk_container_set_border_width(GTK_CONTAINER(quality_vbox), 5); - quality_hbox1 = gtk_hbox_new (FALSE, 5); - gtk_box_pack_start(GTK_BOX(quality_vbox), quality_hbox1, FALSE, - FALSE, 0); + quality_hbox1 = gtk_hbox_new (false, 5); + gtk_box_pack_start(GTK_BOX(quality_vbox), quality_hbox1, false, false, 0); /* Algorithm Quality */ alg_quality_frame = gtk_frame_new(_("Algorithm Quality:")); - gtk_container_set_border_width(GTK_CONTAINER(alg_quality_frame), - 5); - gtk_box_pack_start(GTK_BOX(quality_hbox1), alg_quality_frame, - FALSE, FALSE, 0); - - alg_quality_hbox = gtk_hbox_new (FALSE, 5); - gtk_container_set_border_width(GTK_CONTAINER(alg_quality_hbox), - 10); + gtk_box_pack_start(GTK_BOX(quality_hbox1), alg_quality_frame, true, true, 0); + + alg_quality_hbox = gtk_hbox_new (false, 5); + gtk_container_set_border_width(GTK_CONTAINER(alg_quality_hbox), 5); gtk_container_add(GTK_CONTAINER(alg_quality_frame), alg_quality_hbox); alg_quality_adj = (GtkAdjustment *) gtk_adjustment_new (5, 0, 9, 1, 1, 0); alg_quality_spin = gtk_spin_button_new(GTK_ADJUSTMENT(alg_quality_adj), 8, 0); - gtk_box_pack_start(GTK_BOX(alg_quality_hbox), alg_quality_spin, - TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(alg_quality_hbox), alg_quality_spin, false, false, 0); g_signal_connect (alg_quality_adj, "value-changed", (GCallback) algo_qual, nullptr); gtk_spin_button_set_value(GTK_SPIN_BUTTON(alg_quality_spin), - algo_quality_val); + GET_INT("algo_quality_val")); /* Output Samplerate */ samplerate_frame = gtk_frame_new(_("Output Sample Rate:")); - gtk_container_set_border_width(GTK_CONTAINER(samplerate_frame), 5); - gtk_box_pack_start(GTK_BOX(quality_hbox1), samplerate_frame, FALSE, - FALSE, 0); + gtk_box_pack_start(GTK_BOX(quality_hbox1), samplerate_frame, true, true, 0); - samplerate_hbox = gtk_hbox_new (FALSE, 5); - gtk_container_set_border_width(GTK_CONTAINER(samplerate_hbox), 10); + samplerate_hbox = gtk_hbox_new (false, 5); + gtk_container_set_border_width(GTK_CONTAINER(samplerate_hbox), 5); gtk_container_add(GTK_CONTAINER(samplerate_frame), samplerate_hbox); GtkWidget * combo = gtk_combo_box_text_new (); gtk_combo_box_text_append_text ((GtkComboBoxText *) combo, _("Auto")); + + const int out_samplerate_val = GET_INT("out_samplerate_val"); if (! out_samplerate_val) gtk_combo_box_set_active ((GtkComboBox *) combo, 0); @@ -727,47 +615,42 @@ static void mp3_configure(void) gtk_combo_box_set_active ((GtkComboBox *) combo, 1 + i); } - gtk_box_pack_start ((GtkBox *) samplerate_hbox, combo, FALSE, FALSE, 0); + gtk_box_pack_start ((GtkBox *) samplerate_hbox, combo, false, false, 0); g_signal_connect (combo, "changed", (GCallback) samplerate_changed, nullptr); samplerate_label = gtk_label_new(_("(Hz)")); gtk_misc_set_alignment(GTK_MISC(samplerate_label), 0, 0.5); - gtk_box_pack_start(GTK_BOX(samplerate_hbox), samplerate_label, - FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(samplerate_hbox), samplerate_label, false, false, 0); /* Encoder Quality */ enc_quality_frame = gtk_frame_new(_("Bitrate / Compression Ratio:")); - gtk_container_set_border_width(GTK_CONTAINER(enc_quality_frame), - 5); - gtk_box_pack_start(GTK_BOX(quality_vbox), enc_quality_frame, FALSE, - FALSE, 0); + gtk_box_pack_start(GTK_BOX(quality_vbox), enc_quality_frame, false, false, 0); // vbox sorrounding hbox1 and hbox2 - enc_quality_vbox = gtk_vbox_new (FALSE, 5); - gtk_container_set_border_width(GTK_CONTAINER(enc_quality_vbox), 10); + enc_quality_vbox = gtk_vbox_new (false, 5); + gtk_container_set_border_width(GTK_CONTAINER(enc_quality_vbox), 5); // pack vbox to frame gtk_container_add(GTK_CONTAINER(enc_quality_frame), enc_quality_vbox); // hbox1 for bitrate - hbox1 = gtk_hbox_new (FALSE, 5); + hbox1 = gtk_hbox_new (false, 5); gtk_container_add(GTK_CONTAINER(enc_quality_vbox), hbox1); // radio 1 enc_radio1 = gtk_radio_button_new(nullptr); - if (enc_toggle_val == 0) - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enc_radio1), TRUE); - gtk_box_pack_start(GTK_BOX(hbox1), enc_radio1, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox1), enc_radio1, false, false, 0); // label 1 enc_quality_label1 = gtk_label_new(_("Bitrate (kbps):")); - gtk_box_pack_start(GTK_BOX(hbox1), enc_quality_label1, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox1), enc_quality_label1, false, false, 0); // bitrate menu combo = gtk_combo_box_text_new (); + const int bitrate_val = GET_INT("bitrate_val"); for (int i = 0; i < aud::n_elems (available_bitrates); i ++) { gtk_combo_box_text_append_text ((GtkComboBoxText *) combo, @@ -777,37 +660,37 @@ static void mp3_configure(void) gtk_combo_box_set_active ((GtkComboBox *) combo, i); } - gtk_box_pack_start ((GtkBox *) hbox1, combo, FALSE, FALSE, 0); + gtk_box_pack_start ((GtkBox *) hbox1, combo, false, false, 0); g_signal_connect (combo, "changed", (GCallback) bitrate_changed, nullptr); // hbox2 for compression ratio - hbox2 = gtk_hbox_new (FALSE, 5); + hbox2 = gtk_hbox_new (false, 5); gtk_container_add(GTK_CONTAINER(enc_quality_vbox), hbox2); // radio 2 enc_radio2 = gtk_radio_button_new_from_widget(GTK_RADIO_BUTTON(enc_radio1)); - if (enc_toggle_val == 1) - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enc_radio2), - TRUE); - // pack radio 2 - gtk_box_pack_start(GTK_BOX(hbox2), enc_radio2, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox2), enc_radio2, false, false, 0); // label enc_quality_label2 = gtk_label_new(_("Compression ratio:")); - gtk_box_pack_start(GTK_BOX(hbox2), enc_quality_label2, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox2), enc_quality_label2, false, false, 0); // comp-ratio spin - compression_adj = (GtkAdjustment *) gtk_adjustment_new (11, 0, 100, 1, - 1, 0); + compression_adj = (GtkAdjustment *) gtk_adjustment_new (11, 0, 100, 1, 1, 0); compression_spin = gtk_spin_button_new(GTK_ADJUSTMENT(compression_adj), 8, 0); - gtk_box_pack_end(GTK_BOX(hbox2), compression_spin, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox2), compression_spin, false, false, 0); g_signal_connect (compression_adj, "value-changed", (GCallback) compression_change, nullptr); gtk_spin_button_set_value(GTK_SPIN_BUTTON(compression_spin), - compression_val); + GET_DOUBLE("compression_val")); + + if (GET_INT("enc_toggle_val") == 0) + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enc_radio1), true); + else + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enc_radio2), true); // radio button signale connect g_signal_connect (enc_radio1, "toggled", (GCallback) encoding_toggle, @@ -818,16 +701,15 @@ static void mp3_configure(void) /* Audio Mode */ mode_frame = gtk_frame_new(_("Audio Mode:")); - gtk_container_set_border_width(GTK_CONTAINER(mode_frame), 5); - gtk_box_pack_start(GTK_BOX(quality_vbox), mode_frame, FALSE, FALSE, - 0); + gtk_box_pack_start(GTK_BOX(quality_vbox), mode_frame, false, false, 0); - mode_hbox = gtk_hbox_new (FALSE, 10); - gtk_container_set_border_width(GTK_CONTAINER(mode_hbox), 10); + mode_hbox = gtk_hbox_new (false, 5); + gtk_container_set_border_width(GTK_CONTAINER(mode_hbox), 5); gtk_container_add(GTK_CONTAINER(mode_frame), mode_hbox); combo = gtk_combo_box_text_new (); + const int audio_mode_val = GET_INT("audio_mode_val"); for (int i = 0; i < MODES; i ++) { gtk_combo_box_text_append_text ((GtkComboBoxText *) combo, @@ -837,42 +719,38 @@ static void mp3_configure(void) gtk_combo_box_set_active ((GtkComboBox *) combo, i); } - gtk_box_pack_start ((GtkBox *) mode_hbox, combo, FALSE, FALSE, 0); + gtk_box_pack_start ((GtkBox *) mode_hbox, combo, false, false, 0); g_signal_connect (combo, "changed", (GCallback) mode_changed, nullptr); /* Misc */ misc_frame = gtk_frame_new(_("Miscellaneous:")); - gtk_container_set_border_width(GTK_CONTAINER(misc_frame), 5); - gtk_box_pack_start(GTK_BOX(quality_vbox), misc_frame, FALSE, FALSE, - 0); + gtk_box_pack_start(GTK_BOX(quality_vbox), misc_frame, false, false, 0); - misc_vbox = gtk_vbox_new (FALSE, 5); + misc_vbox = gtk_vbox_new (false, 5); gtk_container_set_border_width(GTK_CONTAINER(misc_vbox), 5); gtk_container_add(GTK_CONTAINER(misc_frame), misc_vbox); enforce_iso_toggle = gtk_check_button_new_with_label (_("Enforce strict ISO compliance")); - gtk_box_pack_start(GTK_BOX(misc_vbox), enforce_iso_toggle, TRUE, - TRUE, 2); + gtk_box_pack_start(GTK_BOX(misc_vbox), enforce_iso_toggle, true, true, 0); g_signal_connect (enforce_iso_toggle, "toggled", (GCallback) toggle_enforce_iso, nullptr); - if (enforce_iso_val == 1) + if (GET_INT("enforce_iso_val") == 1) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON - (enforce_iso_toggle), TRUE); + (enforce_iso_toggle), true); error_protection_toggle = gtk_check_button_new_with_label(_("Error protection")); - gtk_box_pack_start(GTK_BOX(misc_vbox), error_protection_toggle, - TRUE, TRUE, 2); + gtk_box_pack_start(GTK_BOX(misc_vbox), error_protection_toggle, true, true, 0); g_signal_connect (error_protection_toggle, "toggled", (GCallback) toggle_error_protect, nullptr); - if (error_protect_val == 1) + if (GET_INT("error_protect_val") == 1) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON - (error_protection_toggle), TRUE); + (error_protection_toggle), true); /* Add the Notebook */ gtk_notebook_append_page(GTK_NOTEBOOK(notebook), quality_vbox, @@ -880,46 +758,41 @@ static void mp3_configure(void) /* VBR/ABR */ - vbr_vbox = gtk_vbox_new (FALSE, 5); + vbr_vbox = gtk_vbox_new (false, 5); gtk_container_set_border_width(GTK_CONTAINER(vbr_vbox), 5); /* Toggle VBR */ vbr_toggle = gtk_check_button_new_with_label(_("Enable VBR/ABR")); - gtk_box_pack_start(GTK_BOX(vbr_vbox), vbr_toggle, FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(vbr_vbox), vbr_toggle, false, false, 0); g_signal_connect (vbr_toggle, "toggled", (GCallback) toggle_vbr, nullptr); - vbr_options_vbox = gtk_vbox_new (FALSE, 0); + vbr_options_vbox = gtk_vbox_new (false, 5); gtk_container_add(GTK_CONTAINER(vbr_vbox), vbr_options_vbox); - gtk_widget_set_sensitive(vbr_options_vbox, FALSE); + gtk_widget_set_sensitive(vbr_options_vbox, false); /* Choose VBR/ABR */ vbr_type_frame = gtk_frame_new(_("Type:")); - gtk_container_set_border_width(GTK_CONTAINER(vbr_type_frame), 5); - gtk_box_pack_start(GTK_BOX(vbr_options_vbox), vbr_type_frame, - FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(vbr_options_vbox), vbr_type_frame, false, false, 0); - vbr_type_hbox = gtk_hbox_new (FALSE, 5); + vbr_type_hbox = gtk_hbox_new (false, 5); gtk_container_set_border_width(GTK_CONTAINER(vbr_type_hbox), 5); gtk_container_add(GTK_CONTAINER(vbr_type_frame), vbr_type_hbox); vbr_type_radio1 = gtk_radio_button_new_with_label(nullptr, "VBR"); - gtk_box_pack_start(GTK_BOX(vbr_type_hbox), vbr_type_radio1, TRUE, - TRUE, 2); - if (vbr_type == 0) - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON - (vbr_type_radio1), TRUE); + gtk_box_pack_start(GTK_BOX(vbr_type_hbox), vbr_type_radio1, false, false, 0); vbr_type_radio2 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON (vbr_type_radio1), "ABR"); - gtk_box_pack_start(GTK_BOX(vbr_type_hbox), vbr_type_radio2, TRUE, - TRUE, 2); - if (vbr_type == 1) - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON - (vbr_type_radio2), TRUE); + gtk_box_pack_start(GTK_BOX(vbr_type_hbox), vbr_type_radio2, false, false, 0); + + if (GET_INT("vbr_type") == 0) + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(vbr_type_radio1), true); + else + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(vbr_type_radio2), true); g_signal_connect (vbr_type_radio1, "toggled", (GCallback) vbr_abr_toggle, (void *) "VBR"); @@ -929,28 +802,23 @@ static void mp3_configure(void) /* VBR Options */ vbr_frame = gtk_frame_new(_("VBR Options:")); - gtk_container_set_border_width(GTK_CONTAINER(vbr_frame), 5); - gtk_box_pack_start(GTK_BOX(vbr_options_vbox), vbr_frame, FALSE, - FALSE, 2); + gtk_box_pack_start(GTK_BOX(vbr_options_vbox), vbr_frame, false, false, 0); - vbr_options_vbox2 = gtk_vbox_new (FALSE, 5); - gtk_container_set_border_width(GTK_CONTAINER(vbr_options_vbox2), - 5); + vbr_options_vbox2 = gtk_vbox_new (false, 5); + gtk_container_set_border_width(GTK_CONTAINER(vbr_options_vbox2), 5); gtk_container_add(GTK_CONTAINER(vbr_frame), vbr_options_vbox2); - vbr_options_hbox1 = gtk_hbox_new (FALSE, 5); - gtk_container_set_border_width(GTK_CONTAINER(vbr_options_hbox1), - 5); + vbr_options_hbox1 = gtk_hbox_new (false, 5); gtk_container_add(GTK_CONTAINER(vbr_options_vbox2), vbr_options_hbox1); vbr_min_label = gtk_label_new(_("Minimum bitrate (kbps):")); gtk_misc_set_alignment(GTK_MISC(vbr_min_label), 0, 0.5); - gtk_box_pack_start(GTK_BOX(vbr_options_hbox1), vbr_min_label, TRUE, - TRUE, 0); + gtk_box_pack_start(GTK_BOX(vbr_options_hbox1), vbr_min_label, false, false, 0); combo = gtk_combo_box_text_new (); + const int vbr_min_val = GET_INT("vbr_min_val"); for (int i = 0; i < aud::n_elems (available_bitrates); i ++) { gtk_combo_box_text_append_text ((GtkComboBoxText *) combo, @@ -960,23 +828,20 @@ static void mp3_configure(void) gtk_combo_box_set_active ((GtkComboBox *) combo, i); } - gtk_box_pack_start ((GtkBox *) vbr_options_hbox1, combo, FALSE, FALSE, - 0); + gtk_box_pack_start ((GtkBox *) vbr_options_hbox1, combo, false, false, 0); g_signal_connect (combo, "changed", (GCallback) vbr_min_changed, nullptr); - vbr_options_hbox2 = gtk_hbox_new (FALSE, 5); - gtk_container_set_border_width(GTK_CONTAINER(vbr_options_hbox2), - 5); + vbr_options_hbox2 = gtk_hbox_new (false, 5); gtk_container_add(GTK_CONTAINER(vbr_options_vbox2), vbr_options_hbox2); vbr_max_label = gtk_label_new(_("Maximum bitrate (kbps):")); gtk_misc_set_alignment(GTK_MISC(vbr_max_label), 0, 0.5); - gtk_box_pack_start(GTK_BOX(vbr_options_hbox2), vbr_max_label, TRUE, - TRUE, 0); + gtk_box_pack_start(GTK_BOX(vbr_options_hbox2), vbr_max_label, false, false, 0); combo = gtk_combo_box_text_new (); + const int vbr_max_val = GET_INT("vbr_max_val"); for (int i = 0; i < aud::n_elems (available_bitrates); i ++) { gtk_combo_box_text_append_text ((GtkComboBoxText *) combo, @@ -986,40 +851,37 @@ static void mp3_configure(void) gtk_combo_box_set_active ((GtkComboBox *) combo, i); } - gtk_box_pack_start ((GtkBox *) vbr_options_hbox2, combo, FALSE, FALSE, - 0); + gtk_box_pack_start ((GtkBox *) vbr_options_hbox2, combo, false, false, 0); g_signal_connect (combo, "changed", (GCallback) vbr_max_changed, nullptr); enforce_min_toggle = gtk_check_button_new_with_label (_("Strictly enforce minimum bitrate")); - gtk_box_pack_start(GTK_BOX(vbr_options_vbox2), enforce_min_toggle, - FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(vbr_options_vbox2), enforce_min_toggle, false, false, 0); g_signal_connect (enforce_min_toggle, "toggled", (GCallback) toggle_enforce_min, nullptr); - if (enforce_min_val == 1) + if (GET_INT("enforce_min_val") == 1) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON - (enforce_min_toggle), TRUE); + (enforce_min_toggle), true); /* ABR Options */ abr_frame = gtk_frame_new(_("ABR Options:")); - gtk_container_set_border_width(GTK_CONTAINER(abr_frame), 5); - gtk_box_pack_start(GTK_BOX(vbr_options_vbox), abr_frame, FALSE, - FALSE, 2); - gtk_widget_set_sensitive(abr_frame, FALSE); + gtk_box_pack_start(GTK_BOX(vbr_options_vbox), abr_frame, false, false, 0); + gtk_widget_set_sensitive(abr_frame, false); - abr_hbox = gtk_hbox_new (FALSE, 5); + abr_hbox = gtk_hbox_new (false, 5); gtk_container_set_border_width(GTK_CONTAINER(abr_hbox), 5); gtk_container_add(GTK_CONTAINER(abr_frame), abr_hbox); abr_label = gtk_label_new(_("Average bitrate (kbps):")); gtk_misc_set_alignment(GTK_MISC(abr_label), 0, 0.5); - gtk_box_pack_start(GTK_BOX(abr_hbox), abr_label, TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(abr_hbox), abr_label, false, false, 0); combo = gtk_combo_box_text_new (); + const int abr_val = GET_INT("abr_val"); for (int i = 0; i < aud::n_elems (available_bitrates); i ++) { gtk_combo_box_text_append_text ((GtkComboBoxText *) combo, @@ -1029,46 +891,40 @@ static void mp3_configure(void) gtk_combo_box_set_active ((GtkComboBox *) combo, i); } - gtk_box_pack_start ((GtkBox *) abr_hbox, combo, FALSE, FALSE, - 0); + gtk_box_pack_start ((GtkBox *) abr_hbox, combo, false, false, 0); g_signal_connect (combo, "changed", (GCallback) abr_changed, nullptr); /* Quality Level */ - vbr_options_hbox3 = gtk_hbox_new (FALSE, 5); - gtk_container_set_border_width(GTK_CONTAINER(vbr_options_hbox3), - 5); + vbr_options_hbox3 = gtk_hbox_new (false, 5); gtk_container_add(GTK_CONTAINER(vbr_options_vbox), vbr_options_hbox3); vbr_quality_label = gtk_label_new(_("VBR quality level:")); gtk_misc_set_alignment(GTK_MISC(vbr_quality_label), 0, 0.5); - gtk_box_pack_start(GTK_BOX(vbr_options_hbox3), vbr_quality_label, - TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(vbr_options_hbox3), vbr_quality_label, false, false, 0); vbr_quality_adj = (GtkAdjustment *) gtk_adjustment_new (4, 0, 9, 1, 1, 0); vbr_quality_spin = gtk_spin_button_new(GTK_ADJUSTMENT(vbr_quality_adj), 8, 0); - gtk_box_pack_start(GTK_BOX(vbr_options_hbox3), vbr_quality_spin, - TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(vbr_options_hbox3), vbr_quality_spin, false, false, 0); g_signal_connect (vbr_quality_adj, "value-changed", (GCallback) vbr_qual, nullptr); gtk_spin_button_set_value(GTK_SPIN_BUTTON(vbr_quality_spin), - vbr_quality_val); + GET_INT("vbr_quality_val")); /* Xing Header */ xing_header_toggle = gtk_check_button_new_with_label(_("Omit Xing VBR header")); - gtk_box_pack_start(GTK_BOX(vbr_options_vbox), xing_header_toggle, - FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(vbr_options_vbox), xing_header_toggle, false, false, 0); g_signal_connect (xing_header_toggle, "toggled", (GCallback) toggle_xing, nullptr); - if (toggle_xing_val == 0) + if (GET_INT("toggle_xing_val") == 0) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON - (xing_header_toggle), TRUE); + (xing_header_toggle), true); /* Add the Notebook */ @@ -1077,18 +933,15 @@ static void mp3_configure(void) /* Tags */ - tags_vbox = gtk_vbox_new (FALSE, 5); + tags_vbox = gtk_vbox_new (false, 5); gtk_container_set_border_width(GTK_CONTAINER(tags_vbox), 5); /* Frame Params */ tags_frames_frame = gtk_frame_new(_("Frame Parameters:")); - gtk_container_set_border_width(GTK_CONTAINER(tags_frames_frame), - 5); - gtk_box_pack_start(GTK_BOX(tags_vbox), tags_frames_frame, FALSE, - FALSE, 2); + gtk_box_pack_start(GTK_BOX(tags_vbox), tags_frames_frame, false, false, 0); - tags_frames_hbox = gtk_hbox_new (FALSE, 5); + tags_frames_hbox = gtk_hbox_new (false, 5); gtk_container_set_border_width(GTK_CONTAINER(tags_frames_hbox), 5); gtk_container_add(GTK_CONTAINER(tags_frames_frame), tags_frames_hbox); @@ -1096,72 +949,66 @@ static void mp3_configure(void) tags_copyright_toggle = gtk_check_button_new_with_label(_("Mark as copyright")); gtk_box_pack_start(GTK_BOX(tags_frames_hbox), - tags_copyright_toggle, FALSE, FALSE, 2); + tags_copyright_toggle, false, false, 0); g_signal_connect (tags_copyright_toggle, "toggled", (GCallback) toggle_copyright, nullptr); - if (mark_copyright_val == 1) + if (GET_INT("mark_copyright_val") == 1) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON - (tags_copyright_toggle), TRUE); + (tags_copyright_toggle), true); tags_original_toggle = gtk_check_button_new_with_label(_("Mark as original")); - gtk_box_pack_start(GTK_BOX(tags_frames_hbox), tags_original_toggle, - FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(tags_frames_hbox), tags_original_toggle, false, false, 0); g_signal_connect (tags_original_toggle, "toggled", (GCallback) toggle_original, nullptr); - if (mark_original_val == 1) + if (GET_INT("mark_original_val") == 1) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON - (tags_original_toggle), TRUE); + (tags_original_toggle), true); /* ID3 Params */ tags_id3_frame = gtk_frame_new(_("ID3 Parameters:")); - gtk_container_set_border_width(GTK_CONTAINER(tags_id3_frame), 5); - gtk_box_pack_start(GTK_BOX(tags_vbox), tags_id3_frame, FALSE, - FALSE, 2); + gtk_box_pack_start(GTK_BOX(tags_vbox), tags_id3_frame, false, false, 0); - tags_id3_vbox = gtk_vbox_new (FALSE, 5); + tags_id3_vbox = gtk_vbox_new (false, 5); gtk_container_set_border_width(GTK_CONTAINER(tags_id3_vbox), 5); gtk_container_add(GTK_CONTAINER(tags_id3_frame), tags_id3_vbox); tags_force_id3v2_toggle = gtk_check_button_new_with_label (_("Force addition of version 2 tag")); - gtk_box_pack_start(GTK_BOX(tags_id3_vbox), tags_force_id3v2_toggle, - FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(tags_id3_vbox), tags_force_id3v2_toggle, false, false, 0); g_signal_connect (tags_force_id3v2_toggle, "toggled", (GCallback) force_v2_toggle, nullptr); - tags_id3_hbox = gtk_hbox_new (FALSE, 5); + tags_id3_hbox = gtk_hbox_new (false, 5); gtk_container_add(GTK_CONTAINER(tags_id3_vbox), tags_id3_hbox); tags_only_v1_toggle = gtk_check_button_new_with_label(_("Only add v1 tag")); - gtk_box_pack_start(GTK_BOX(tags_id3_hbox), tags_only_v1_toggle, - FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(tags_id3_hbox), tags_only_v1_toggle, false, false, 0); g_signal_connect (tags_only_v1_toggle, "toggled", (GCallback) id3_only_version, (void *) "v1"); tags_only_v2_toggle = gtk_check_button_new_with_label(_("Only add v2 tag")); - gtk_box_pack_start(GTK_BOX(tags_id3_hbox), tags_only_v2_toggle, - FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(tags_id3_hbox), tags_only_v2_toggle, false, false, 0); g_signal_connect (tags_only_v2_toggle, "toggled", (GCallback) id3_only_version, (void *) "v2"); - if (force_v2_val == 1) + if (GET_INT("force_v2_val") == 1) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON - (tags_force_id3v2_toggle), TRUE); + (tags_force_id3v2_toggle), true); - if (only_v1_val == 1) + if (GET_INT("only_v1_val") == 1) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON - (tags_only_v1_toggle), TRUE); + (tags_only_v1_toggle), true); - if (only_v2_val == 1) + if (GET_INT("only_v2_val") == 1) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON - (tags_only_v2_toggle), TRUE); + (tags_only_v2_toggle), true); /* Add the Notebook */ @@ -1170,27 +1017,23 @@ static void mp3_configure(void) /* Set States */ - if (vbr_on == 1) + if (GET_INT("vbr_on") == 1) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(vbr_toggle), - TRUE); + true); else gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(vbr_toggle), - FALSE); - - /* Show it! */ + false); - gtk_widget_show_all(configure_win); - } + return notebook; } static int mp3_format_required (int fmt) { - return FMT_S16_NE; + return FMT_FLOAT; } FileWriterImpl mp3_plugin = { mp3_init, - mp3_configure, mp3_open, mp3_write, mp3_close, diff --git a/src/filewriter/plugins.h b/src/filewriter/plugins.h deleted file mode 100644 index 3293295..0000000 --- a/src/filewriter/plugins.h +++ /dev/null @@ -1,39 +0,0 @@ -/* FileWriter-Plugin - * (C) copyright 2007 merging of Disk Writer and Out-Lame by Michael Färber - * - * Original Out-Lame-Plugin: - * (C) copyright 2002 Lars Siebold <khandha5@gmx.net> - * (C) copyright 2006-2007 porting to audacious by Yoshiki Yazawa <yaz@cc.rim.or.jp> - * - * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef PLUGINS_H -#define PLUGINS_H - -#include "filewriter.h" - -extern FileWriterImpl wav_plugin; -#ifdef FILEWRITER_MP3 -extern FileWriterImpl mp3_plugin; -#endif -#ifdef FILEWRITER_VORBIS -extern FileWriterImpl vorbis_plugin; -#endif -#ifdef FILEWRITER_FLAC -extern FileWriterImpl flac_plugin; -#endif - -#endif diff --git a/src/filewriter/vorbis.cc b/src/filewriter/vorbis.cc index c97ac3d..e8d2107 100644 --- a/src/filewriter/vorbis.cc +++ b/src/filewriter/vorbis.cc @@ -19,7 +19,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "plugins.h" +#include "filewriter.h" #ifdef FILEWRITER_VORBIS @@ -44,14 +44,14 @@ static const char * const vorbis_defaults[] = { "base_quality", "0.5", nullptr}; -static double v_base_quality; +#define GET_DOUBLE(n) aud_get_double("filewriter_vorbis", n) +#define SET_DOUBLE(n, v) aud_set_double("filewriter_vorbis", n, v) + static int channels; static void vorbis_init () { aud_config_set_defaults ("filewriter_vorbis", vorbis_defaults); - - v_base_quality = aud_get_double ("filewriter_vorbis", "base_quality"); } static void add_string_from_tuple (vorbis_comment * vc, const char * name, @@ -88,7 +88,7 @@ static bool vorbis_open (VFSFile & file, const format_info & info, const Tuple & if ((scrint = tuple.get_int (Tuple::Year)) > 0) vorbis_comment_add_tag(&vc, "year", int_to_str (scrint)); - if (vorbis_encode_init_vbr (& vi, info.channels, info.frequency, v_base_quality)) + if (vorbis_encode_init_vbr(& vi, info.channels, info.frequency, GET_DOUBLE("base_quality"))) { vorbis_info_clear(&vi); return false; @@ -178,57 +178,42 @@ static void vorbis_close (VFSFile & file) } /* configuration stuff */ -static GtkWidget *configure_win = nullptr; static GtkWidget *quality_frame, *quality_vbox, *quality_hbox1, *quality_spin, *quality_label; static GtkAdjustment * quality_adj; static void quality_change(GtkAdjustment *adjustment, void * user_data) { - v_base_quality = gtk_spin_button_get_value ((GtkSpinButton *) quality_spin) / 10; - aud_set_double ("filewriter_vorbis", "base_quality", v_base_quality); + SET_DOUBLE ("base_quality", gtk_spin_button_get_value ((GtkSpinButton *) quality_spin) / 10); } -static void vorbis_configure(void) +void * vorbis_configure () { - if (! configure_win) - { - configure_win = gtk_dialog_new_with_buttons - (_("Vorbis Encoder Configuration"), nullptr, (GtkDialogFlags) 0, - _("_Close"), GTK_RESPONSE_CLOSE, nullptr); - - g_signal_connect (configure_win, "response", (GCallback) gtk_widget_destroy, nullptr); - g_signal_connect (configure_win, "destroy", (GCallback) - gtk_widget_destroyed, & configure_win); - - GtkWidget * vbox = gtk_dialog_get_content_area ((GtkDialog *) configure_win); + GtkWidget * vbox = gtk_vbox_new (false, 5); /* quality options */ quality_frame = gtk_frame_new(_("Quality")); - gtk_container_set_border_width(GTK_CONTAINER(quality_frame), 5); - gtk_box_pack_start(GTK_BOX(vbox), quality_frame, FALSE, FALSE, 2); + gtk_box_pack_start(GTK_BOX(vbox), quality_frame, false, false, 0); - quality_vbox = gtk_vbox_new (FALSE, 5); - gtk_container_set_border_width(GTK_CONTAINER(quality_vbox), 10); + quality_vbox = gtk_vbox_new (false, 5); + gtk_container_set_border_width(GTK_CONTAINER(quality_vbox), 5); gtk_container_add(GTK_CONTAINER(quality_frame), quality_vbox); /* quality option: vbr level */ - quality_hbox1 = gtk_hbox_new (FALSE, 5); - gtk_container_set_border_width(GTK_CONTAINER(quality_hbox1), 10); + quality_hbox1 = gtk_hbox_new (false, 5); gtk_container_add(GTK_CONTAINER(quality_vbox), quality_hbox1); quality_label = gtk_label_new(_("Quality level (0 - 10):")); gtk_misc_set_alignment(GTK_MISC(quality_label), 0, 0.5); - gtk_box_pack_start(GTK_BOX(quality_hbox1), quality_label, TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(quality_hbox1), quality_label, false, false, 0); quality_adj = (GtkAdjustment *) gtk_adjustment_new (5, 0, 10, 0.1, 1, 0); quality_spin = gtk_spin_button_new(GTK_ADJUSTMENT(quality_adj), 1, 2); - gtk_box_pack_start(GTK_BOX(quality_hbox1), quality_spin, TRUE, TRUE, 0); + gtk_box_pack_start(GTK_BOX(quality_hbox1), quality_spin, false, false, 0); g_signal_connect(G_OBJECT(quality_adj), "value-changed", G_CALLBACK(quality_change), nullptr); - gtk_spin_button_set_value(GTK_SPIN_BUTTON(quality_spin), (v_base_quality * 10)); - } + gtk_spin_button_set_value(GTK_SPIN_BUTTON(quality_spin), GET_DOUBLE("base_quality") * 10); - gtk_widget_show_all(configure_win); + return vbox; } static int vorbis_format_required (int fmt) @@ -238,7 +223,6 @@ static int vorbis_format_required (int fmt) FileWriterImpl vorbis_plugin = { vorbis_init, - vorbis_configure, vorbis_open, vorbis_write, vorbis_close, diff --git a/src/filewriter/wav.cc b/src/filewriter/wav.cc index ab914fd..dd011ff 100644 --- a/src/filewriter/wav.cc +++ b/src/filewriter/wav.cc @@ -21,7 +21,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "plugins.h" +#include "filewriter.h" #include <string.h> #include <libaudcore/runtime.h> @@ -144,7 +144,6 @@ static int wav_format_required (int fmt) FileWriterImpl wav_plugin = { nullptr, // init - nullptr, // configure wav_open, wav_write, wav_close, diff --git a/src/flacng/metadata.cc b/src/flacng/metadata.cc index 837f844..cb413bf 100644 --- a/src/flacng/metadata.cc +++ b/src/flacng/metadata.cc @@ -19,7 +19,6 @@ * */ -#include <limits.h> #include <stdlib.h> #include <string.h> @@ -237,54 +236,6 @@ ERR: return data; } -static void parse_gain_text(const char *text, int *value, int *unit) -{ - int sign = 1; - - *value = 0; - *unit = 1; - - if (*text == '-') - { - sign = -1; - text++; - } - - while (*text >= '0' && *text <= '9') - { - *value = *value * 10 + (*text - '0'); - text++; - } - - if (*text == '.') - { - text++; - - while (*text >= '0' && *text <= '9' && *value < INT_MAX / 10) - { - *value = *value * 10 + (*text - '0'); - *unit = *unit * 10; - text++; - } - } - - *value = *value * sign; -} - -static void set_gain_info(Tuple &tuple, Tuple::Field field, Tuple::Field unit_field, const char *text) -{ - int value, unit; - - parse_gain_text(text, &value, &unit); - - if (tuple.get_value_type (unit_field) == Tuple::Int) - value = value * (int64_t) tuple.get_int (unit_field) / unit; - else - tuple.set_int (unit_field, unit); - - tuple.set_int (field, value); -} - static void add_text (Tuple & tuple, Tuple::Field field, const char * value) { String cur = tuple.get_str (field); @@ -323,13 +274,13 @@ static void parse_comment (Tuple & tuple, const char * key, const char * value) else if (!strcmp_nocase(key, "DATE")) tuple.set_int(Tuple::Year, atoi(value)); else if (!strcmp_nocase(key, "REPLAYGAIN_TRACK_GAIN")) - set_gain_info(tuple, Tuple::TrackGain, Tuple::GainDivisor, value); + tuple.set_gain(Tuple::TrackGain, Tuple::GainDivisor, value); else if (!strcmp_nocase(key, "REPLAYGAIN_TRACK_PEAK")) - set_gain_info(tuple, Tuple::TrackPeak, Tuple::PeakDivisor, value); + tuple.set_gain(Tuple::TrackPeak, Tuple::PeakDivisor, value); else if (!strcmp_nocase(key, "REPLAYGAIN_ALBUM_GAIN")) - set_gain_info(tuple, Tuple::AlbumGain, Tuple::GainDivisor, value); + tuple.set_gain(Tuple::AlbumGain, Tuple::GainDivisor, value); else if (!strcmp_nocase(key, "REPLAYGAIN_ALBUM_PEAK")) - set_gain_info(tuple, Tuple::AlbumPeak, Tuple::PeakDivisor, value); + tuple.set_gain(Tuple::AlbumPeak, Tuple::PeakDivisor, value); } Tuple FLACng::read_tuple(const char *filename, VFSFile &file) diff --git a/src/gio/gio.cc b/src/gio/gio.cc index 0d3d3fd..73f020e 100644 --- a/src/gio/gio.cc +++ b/src/gio/gio.cc @@ -29,7 +29,6 @@ #include <libaudcore/plugin.h> #include <libaudcore/runtime.h> - static const char gio_about[] = N_("GIO Plugin for Audacious\n" "Copyright 2009-2012 John Lindgren"); @@ -65,10 +64,6 @@ protected: int fseek (int64_t offset, VFSSeekType whence); int64_t ftell (); - - int getc (); - int ungetc (int c); - bool feof (); int ftruncate (int64_t length); @@ -83,6 +78,7 @@ private: GInputStream * m_istream = nullptr; GOutputStream * m_ostream = nullptr; GSeekable * m_seekable = nullptr; + bool m_eof = false; }; #define CHECK_ERROR(op, name) do { \ @@ -176,7 +172,7 @@ FAILED: GIOFile::~GIOFile () { - GError * error = 0; + GError * error = nullptr; if (m_iostream) { @@ -217,7 +213,7 @@ VFSImpl * GIOTransport::fopen (const char * filename, const char * mode, String int64_t GIOFile::fread (void * buf, int64_t size, int64_t nitems) { - GError * error = 0; + GError * error = nullptr; if (! m_istream) { @@ -233,6 +229,8 @@ int64_t GIOFile::fread (void * buf, int64_t size, int64_t nitems) int64_t part = g_input_stream_read (m_istream, buf, remain, 0, & error); CHECK_ERROR ("read from", m_filename); + m_eof = (part == 0); + if (part <= 0) break; @@ -247,7 +245,7 @@ FAILED: int64_t GIOFile::fwrite (const void * buf, int64_t size, int64_t nitems) { - GError * error = 0; + GError * error = nullptr; if (! m_ostream) { @@ -277,7 +275,7 @@ FAILED: int GIOFile::fseek (int64_t offset, VFSSeekType whence) { - GError * error = 0; + GError * error = nullptr; GSeekType gwhence; switch (whence) @@ -299,6 +297,8 @@ int GIOFile::fseek (int64_t offset, VFSSeekType whence) g_seekable_seek (m_seekable, offset, gwhence, nullptr, & error); CHECK_ERROR ("seek within", m_filename); + m_eof = (whence == VFS_SEEK_END && offset == 0); + return 0; FAILED: @@ -310,35 +310,20 @@ int64_t GIOFile::ftell () return g_seekable_tell (m_seekable); } -int GIOFile::getc () -{ - unsigned char c; - return (fread (& c, 1, 1) == 1) ? c : -1; -} - -int GIOFile::ungetc (int c) -{ - return (! fseek (-1, VFS_SEEK_CUR)) ? c : -1; -} - bool GIOFile::feof () { - int test = getc (); - - if (test < 0) - return TRUE; - - ungetc (test); - return FALSE; + return m_eof; } int GIOFile::ftruncate (int64_t length) { - GError * error = 0; + GError * error = nullptr; g_seekable_truncate (m_seekable, length, nullptr, & error); CHECK_ERROR ("truncate", m_filename); + m_eof = (g_seekable_tell (m_seekable) >= length); + return 0; FAILED: @@ -347,41 +332,38 @@ FAILED: int64_t GIOFile::fsize () { - GError * error = 0; - int64_t size; - - /* Audacious core expects one of two cases: - * 1) File size is known and file is seekable. - * 2) File size is unknown and file is not seekable. - * Therefore, we return -1 for size if file is not seekable. */ if (! g_seekable_can_seek (m_seekable)) return -1; - GFileInfo * info = g_file_query_info (m_file, - G_FILE_ATTRIBUTE_STANDARD_SIZE, (GFileQueryInfoFlags) 0, 0, & error); - CHECK_ERROR ("get size of", m_filename); + GError * error = nullptr; + int64_t saved_pos = g_seekable_tell (m_seekable); + int64_t size = -1; + + g_seekable_seek (m_seekable, 0, G_SEEK_END, nullptr, & error); + CHECK_ERROR ("seek within", m_filename); - size = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_STANDARD_SIZE); + size = g_seekable_tell (m_seekable); - g_object_unref (info); - return size; + g_seekable_seek (m_seekable, saved_pos, G_SEEK_SET, nullptr, & error); + CHECK_ERROR ("seek within", m_filename); + + m_eof = (saved_pos >= size); FAILED: - return -1; + return size; } int GIOFile::fflush () { - int result; - GError * error = nullptr; - if (! m_ostream) return 0; /* no-op */ - result = g_output_stream_flush (m_ostream, nullptr, & error); + GError * error = nullptr; + + g_output_stream_flush (m_ostream, nullptr, & error); CHECK_ERROR ("flush", m_filename); - return result; + return 0; FAILED: return -1; diff --git a/src/gl-spectrum-qt/gl-spectrum.cc b/src/gl-spectrum-qt/gl-spectrum.cc index f081f25..ea85e39 100644 --- a/src/gl-spectrum-qt/gl-spectrum.cc +++ b/src/gl-spectrum-qt/gl-spectrum.cc @@ -25,6 +25,7 @@ #include <math.h> #include <string.h> +#define AUD_PLUGIN_QT_ONLY #include <libaudcore/i18n.h> #include <libaudcore/plugin.h> @@ -50,7 +51,7 @@ class GLSpectrumQt : public VisPlugin { public: static constexpr PluginInfo info = { - N_("OpenGL Spectrum Analyzer (Qt)"), + N_("OpenGL Spectrum Analyzer"), PACKAGE, gl_about }; diff --git a/src/gl-spectrum/gl-spectrum.cc b/src/gl-spectrum/gl-spectrum.cc index 0f4f6d6..2deb4af 100644 --- a/src/gl-spectrum/gl-spectrum.cc +++ b/src/gl-spectrum/gl-spectrum.cc @@ -24,6 +24,7 @@ #include <math.h> #include <string.h> +#define AUD_PLUGIN_GLIB_ONLY #include <libaudcore/i18n.h> #include <libaudcore/plugin.h> @@ -228,7 +229,6 @@ static void draw_bars () glTranslatef (0.0f, -0.5f, -5.0f); glRotatef (38.0f, 1.0f, 0.0f, 0.0f); glRotatef (s_angle + 180.0f, 0.0f, 1.0f, 0.0f); - glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); for (int i = 0; i < NUM_BANDS; i ++) { @@ -242,7 +242,6 @@ static void draw_bars () } } - glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); glPopMatrix (); } @@ -258,36 +257,10 @@ static gboolean draw_cb (GtkWidget * widget) return false; #endif - GtkAllocation alloc; - gtk_widget_get_allocation (widget, & alloc); - glViewport (0, 0, alloc.width, alloc.height); - - glDisable (GL_BLEND); - glMatrixMode (GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glFrustum (-1.1f, 1, -1.5f, 1, 2, 10); - glMatrixMode (GL_MODELVIEW); - glPushMatrix (); - glLoadIdentity (); - glEnable (GL_DEPTH_TEST); - glDepthFunc (GL_LESS); - glPolygonMode (GL_FRONT, GL_FILL); - glEnable (GL_BLEND); - glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glClearColor (0, 0, 0, 1); glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); draw_bars (); - glPopMatrix (); - glMatrixMode (GL_PROJECTION); - glPopMatrix (); - glDisable (GL_DEPTH_TEST); - glDisable (GL_BLEND); - glDepthMask (GL_TRUE); - #ifdef GDK_WINDOWING_X11 glXSwapBuffers (s_display, s_xwindow); #endif @@ -299,6 +272,16 @@ static gboolean draw_cb (GtkWidget * widget) return true; } +static void aspect_viewport(GLint width, GLint height) +{ + glViewport (0, 0, width, height); + glMatrixMode (GL_PROJECTION); + glLoadIdentity (); + glFrustum (-1.1f, 1, -1.5f, 1, 2, 10); + glMatrixMode (GL_MODELVIEW); + glLoadIdentity (); +} + static void widget_realized () { GdkWindow * window = gtk_widget_get_window (s_widget); @@ -374,6 +357,18 @@ static void widget_realized () wglMakeCurrent (s_hdc, s_glrc); #endif + + /* Initialize OpenGL */ + GtkAllocation alloc; + gtk_widget_get_allocation (s_widget, & alloc); + + aspect_viewport (alloc.width, alloc.height); + + glEnable (GL_DEPTH_TEST); + glDepthFunc (GL_LESS); + glDepthMask (GL_TRUE); + glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); + glClearColor (0, 0, 0, 1); } static void widget_destroyed () @@ -409,6 +404,11 @@ static void widget_destroyed () #endif } +static void widget_resize (GtkWidget * widget, GdkEvent * event, gpointer data) +{ + aspect_viewport (event->configure.width, event->configure.height); +} + void * GLSpectrum::get_gtk_widget () { if (s_widget) @@ -419,6 +419,7 @@ void * GLSpectrum::get_gtk_widget () g_signal_connect (s_widget, "expose-event", (GCallback) draw_cb, nullptr); g_signal_connect (s_widget, "realize", (GCallback) widget_realized, nullptr); g_signal_connect (s_widget, "destroy", (GCallback) widget_destroyed, nullptr); + g_signal_connect (s_widget, "configure-event", (GCallback) widget_resize, nullptr); /* Disable GTK double buffering */ gtk_widget_set_double_buffered (s_widget, false); diff --git a/src/gtkui/columns.cc b/src/gtkui/columns.cc index 1ba300f..2e53c51 100644 --- a/src/gtkui/columns.cc +++ b/src/gtkui/columns.cc @@ -112,8 +112,13 @@ void pw_col_init () } String widths = aud_get_str ("gtkui", "column_widths"); + if (! str_to_int_array (widths, pw_col_widths, PW_COLS)) - memcpy (pw_col_widths, pw_default_widths, sizeof pw_col_widths); + { + int dpi = audgui_get_dpi (); + for (int i = 0; i < PW_COLS; i ++) + pw_col_widths[i] = pw_default_widths[i] * dpi / 96; + } } struct Column { @@ -295,7 +300,7 @@ void * pw_col_create_chooser () } GtkWidget * hbox = gtk_hbox_new (false, 6); - gtk_widget_set_size_request (hbox, -1, 160); + gtk_widget_set_size_request (hbox, -1, audgui_get_dpi () * 5 / 4); GtkWidget * scroll = gtk_scrolled_window_new (nullptr, nullptr); gtk_scrolled_window_set_policy ((GtkScrolledWindow *) scroll, diff --git a/src/gtkui/layout.cc b/src/gtkui/layout.cc index 3619ea2..08220c6 100644 --- a/src/gtkui/layout.cc +++ b/src/gtkui/layout.cc @@ -25,12 +25,10 @@ #include <libaudcore/i18n.h> #include <libaudcore/runtime.h> #include <libaudcore/plugins.h> +#include <libaudgui/libaudgui-gtk.h> #include "layout.h" -#define DEFAULT_WIDTH 300 -#define DEFAULT_HEIGHT 200 - enum { DOCK_LEFT, DOCK_RIGHT, @@ -61,18 +59,20 @@ static GtkWidget * menu = nullptr; static Item * item_new (const char * name) { + int dpi = audgui_get_dpi (); + Item * item = new Item (); item->name = String (name); item->plugin = nullptr; item->widget = item->vbox = item->paned = item->window = nullptr; item->dock = item->x = item->y = -1; - item->w = DEFAULT_WIDTH; - item->h = DEFAULT_HEIGHT; + item->w = 3 * dpi; + item->h = 2 * dpi; if (! strcmp (name, _("Search Tool"))) { item->dock = DOCK_LEFT; - item->w = 200; + item->w = 2 * dpi; } items = g_list_append (items, item); @@ -209,22 +209,21 @@ static GtkWidget * vbox_new (GtkWidget * widget, const char * name) } typedef struct { - GtkWidget * paned; GtkWidget * widget; bool vertical; int w, h; } RestoreSizeData; -static gboolean restore_size_cb (RestoreSizeData * d) +static void restore_size_cb (GtkPaned * paned, GdkRectangle *, RestoreSizeData * d) { GtkAllocation rect; gtk_widget_get_allocation (d->widget, & rect); - int pos = gtk_paned_get_position ((GtkPaned *) d->paned); + + int pos = gtk_paned_get_position (paned); pos -= d->vertical ? d->h - rect.height : d->w - rect.width; - gtk_paned_set_position ((GtkPaned *) d->paned, pos); + gtk_paned_set_position (paned, pos); - g_slice_free (RestoreSizeData, d); - return false; + g_signal_handlers_disconnect_by_data (paned, d); } static GtkWidget * paned_new (bool vertical, bool after, int w, int h) @@ -246,13 +245,14 @@ static GtkWidget * paned_new (bool vertical, bool after, int w, int h) if (after) { /* hack to set the size of the second pane */ - RestoreSizeData * d = g_slice_new (RestoreSizeData); - d->paned = paned; + auto d = g_new (RestoreSizeData, 1); d->widget = mine; d->vertical = vertical; d->w = w; d->h = h; - g_idle_add ((GSourceFunc) restore_size_cb, d); + + g_signal_connect_data (paned, "size-allocate", (GCallback) + restore_size_cb, d, (GClosureNotify) g_free, (GConnectFlags) 0); } else gtk_paned_set_position ((GtkPaned *) paned, vertical ? h : w); @@ -352,8 +352,7 @@ static void item_add (Item * item) if (item->x >= 0 && item->y >= 0) gtk_window_move ((GtkWindow *) item->window, item->x, item->y); if (item->w > 0 && item->h > 0) - gtk_window_set_default_size ((GtkWindow *) item->window, item->w, - item->h); + gtk_window_set_default_size ((GtkWindow *) item->window, item->w, item->h); gtk_container_add ((GtkContainer *) item->window, item->vbox); gtk_widget_show_all (item->window); @@ -378,8 +377,7 @@ static void item_add (Item * item) parent = item_get_parent (where); g_return_if_fail (parent); - paned = paned_new (! IS_VERTICAL (where->dock), false, where->w, - where->h); + paned = paned_new (! IS_VERTICAL (where->dock), false, where->w, where->h); where->paned = paned; NULL_ON_DESTROY (where->paned); } @@ -388,8 +386,7 @@ static void item_add (Item * item) parent = dock_get_parent (item->dock); g_return_if_fail (parent); - paned = paned_new (IS_VERTICAL (item->dock), IS_AFTER (item->dock), - item->w, item->h); + paned = paned_new (IS_VERTICAL (item->dock), IS_AFTER (item->dock), item->w, item->h); docks[item->dock] = paned; NULL_ON_DESTROY (docks[item->dock]); } diff --git a/src/gtkui/menus.cc b/src/gtkui/menus.cc index 553158c..90d41fb 100644 --- a/src/gtkui/menus.cc +++ b/src/gtkui/menus.cc @@ -21,6 +21,7 @@ #include <gtk/gtk.h> #include <libaudcore/drct.h> +#include <libaudcore/hook.h> #include <libaudcore/i18n.h> #include <libaudcore/interface.h> #include <libaudcore/playlist.h> @@ -50,6 +51,7 @@ static void add_files () { audgui_run_filebrowser (false); } static void add_url () { audgui_show_add_url_window (false); } static void configure_effects () { audgui_show_prefs_for_plugin_type (PluginType::Effect); } +static void configure_output () { audgui_show_prefs_for_plugin_type (PluginType::Output); } static void configure_visualizations () { audgui_show_prefs_for_plugin_type (PluginType::Vis); } static void pl_sort_track () { aud_playlist_sort_by_scheme (aud_playlist_get_active (), Playlist::Track); } @@ -78,12 +80,6 @@ static void pl_sort_selected_custom () { aud_playlist_sort_selected_by_scheme (a static void pl_reverse_selected () { aud_playlist_reverse_selected (aud_playlist_get_active ()); } static void pl_random_selected () { aud_playlist_randomize_selected (aud_playlist_get_active ()); } -static void pl_new () -{ - aud_playlist_insert (-1); - aud_playlist_set_active (aud_playlist_count () - 1); -} - static void pl_play () { aud_playlist_play (aud_playlist_get_active ()); } static void pl_refresh () { aud_playlist_rescan (aud_playlist_get_active ()); } static void pl_remove_failed () { aud_playlist_remove_failed (aud_playlist_get_active ()); } @@ -122,6 +118,15 @@ static GtkWidget * get_services_pl () { return audgui_get_plugin_menu (AudMenuID static void volume_up () { aud_drct_set_volume_main (aud_drct_get_volume_main () + 5); } static void volume_down () { aud_drct_set_volume_main (aud_drct_get_volume_main () - 5); } +static void toggle_record () +{ + if (! aud_drct_enable_record (aud_get_bool ("gtkui", "record"))) + { + aud_set_bool ("gtkui", "record", aud_drct_get_record_enabled ()); + hook_call ("gtkui set record", nullptr); + } +} + static const AudguiMenuItem file_items[] = { MenuCommand (N_("_Open Files ..."), "document-open", 'o', CTRL, open_files), MenuCommand (N_("Open _URL ..."), "folder-remote", 'l', CTRL, open_url), @@ -144,6 +149,7 @@ static const AudguiMenuItem playback_items[] = { MenuSep (), MenuToggle (N_("_Repeat"), nullptr, 'r', CTRL, nullptr, "repeat", nullptr, "set repeat"), MenuToggle (N_("S_huffle"), nullptr, 's', CTRL, nullptr, "shuffle", nullptr, "set shuffle"), + MenuToggle (N_("Shuffle by Albu_m"), nullptr, NONE, nullptr, "album_shuffle", nullptr, "set album_shuffle"), MenuToggle (N_("N_o Playlist Advance"), nullptr, 'n', CTRL, nullptr, "no_playlist_advance", nullptr, "set no_playlist_advance"), MenuToggle (N_("Stop A_fter This Song"), nullptr, 'm', CTRL, nullptr, "stop_after_current_song", nullptr, "set stop_after_current_song"), MenuSep (), @@ -203,7 +209,7 @@ static const AudguiMenuItem playlist_items[] = { MenuSub (N_("Remove _Duplicates"), "edit-copy", {dupe_items}), MenuCommand (N_("Remove _Unavailable Files"), "dialog-warning", NONE, pl_remove_failed), MenuSep (), - MenuCommand (N_("_New"), "document-new", 't', CTRL, pl_new), + MenuCommand (N_("_New"), "document-new", 't', CTRL, (GCallback) aud_playlist_new), MenuCommand (N_("Ren_ame ..."), "insert-text", GDK_KEY_F2, (GdkModifierType) 0, pl_rename), MenuCommand (N_("Remo_ve"), "edit-delete", 'w', CTRL, pl_close), MenuSep (), @@ -218,9 +224,11 @@ static const AudguiMenuItem output_items[] = { MenuCommand (N_("Volume _Up"), "audio-volume-high", '+', CTRL, volume_up), MenuCommand (N_("Volume _Down"), "audio-volume-low", '-', CTRL, volume_down), MenuSep (), - MenuCommand (N_("_Equalizer"), "multimedia-volume-control", 'e', CTRL, audgui_show_equalizer_window), + MenuCommand (N_("_Equalizer ..."), "multimedia-volume-control", 'e', CTRL, audgui_show_equalizer_window), + MenuCommand (N_("E_ffects ..."), nullptr, NONE, configure_effects), MenuSep (), - MenuCommand (N_("E_ffects ..."), nullptr, NONE, configure_effects) + MenuToggle (N_("_Record Stream"), nullptr, 'd', CTRL, "gtkui", "record", toggle_record, "gtkui set record"), + MenuCommand (N_("Audio _Settings ..."), "audio-card", NONE, configure_output) }; static const AudguiMenuItem view_items[] = { diff --git a/src/gtkui/playlist_util.cc b/src/gtkui/playlist_util.cc index 6ecf216..42d1c6a 100644 --- a/src/gtkui/playlist_util.cc +++ b/src/gtkui/playlist_util.cc @@ -17,9 +17,11 @@ * the use of this software. */ +#include <string.h> #include <gtk/gtk.h> #include <libaudcore/audstrings.h> +#include <libaudcore/interface.h> #include <libaudcore/playlist.h> #include <libaudgui/libaudgui.h> #include <libaudgui/list.h> @@ -66,19 +68,25 @@ void playlist_open_folder () int list = aud_playlist_get_active (); int focus = aud_playlist_get_focus (list); - if (focus < 0) + String filename = aud_playlist_entry_get_filename (list, focus); + if (! filename) return; - StringBuf filename = uri_to_filename (aud_playlist_entry_get_filename (list, focus)); - if (! filename) + const char * slash = strrchr (filename, '/'); + if (! slash) return; - char * dirname = g_path_get_dirname (filename); - StringBuf uri = filename_to_uri (dirname); - g_free (dirname); + /* don't trim trailing slash, it may be important */ + StringBuf folder = str_copy (filename, slash + 1 - filename); - GdkScreen * screen = gdk_screen_get_default (); - gtk_show_uri (screen, uri, GDK_CURRENT_TIME, nullptr); + GError * error = nullptr; + gtk_show_uri (gdk_screen_get_default (), folder, GDK_CURRENT_TIME, & error); + + if (error) + { + aud_ui_show_error (error->message); + g_error_free (error); + } } void playlist_queue_toggle () diff --git a/src/gtkui/ui_gtk.cc b/src/gtkui/ui_gtk.cc index b70d005..7b3f8de 100644 --- a/src/gtkui/ui_gtk.cc +++ b/src/gtkui/ui_gtk.cc @@ -22,16 +22,18 @@ #include <gdk/gdkkeysyms.h> #include <gtk/gtk.h> -#include <libaudcore/runtime.h> +#define AUD_PLUGIN_GLIB_ONLY +#include <libaudcore/audstrings.h> #include <libaudcore/drct.h> +#include <libaudcore/hook.h> #include <libaudcore/i18n.h> +#include <libaudcore/mainloop.h> #include <libaudcore/playlist.h> #include <libaudcore/plugin.h> #include <libaudcore/plugins.h> #include <libaudcore/runtime.h> -#include <libaudcore/audstrings.h> -#include <libaudcore/hook.h> #include <libaudgui/libaudgui.h> +#include <libaudgui/libaudgui-gtk.h> #include "gtkui.h" #include "layout.h" @@ -53,13 +55,12 @@ static const char * const gtkui_defaults[] = { "autoscroll", "TRUE", "playlist_columns", "title artist album queued length", "playlist_headers", "TRUE", + "record", "FALSE", "show_remaining_time", "FALSE", "step_size", "5", "player_x", "-1000", "player_y", "-1000", - "player_width", "760", - "player_height", "460", nullptr }; @@ -113,7 +114,6 @@ static PluginHandle * search_tool; static GtkWidget * volume; static bool volume_slider_is_moving = false; -static unsigned update_volume_timeout_source = 0; static unsigned long volume_change_handler_id; static GtkAccelGroup * accel; @@ -121,14 +121,13 @@ static GtkAccelGroup * accel; static GtkWidget * window, * vbox_outer, * menu_box, * menu, * toolbar, * vbox, * infoarea, * statusbar; static GtkToolItem * menu_button, * search_button, * button_play, * button_stop, - * button_shuffle, * button_repeat; + * button_record, * button_shuffle, * button_repeat; static GtkWidget * slider, * label_time; static GtkWidget * menu_main, * menu_rclick, * menu_tab; -static gboolean slider_is_moving = false; +static bool slider_is_moving = false; static int slider_seek_time = -1; -static unsigned delayed_title_change_source = 0; -static unsigned update_song_timeout_source = 0; +static QueuedFunc delayed_title_change; static void save_window_size () { @@ -144,11 +143,17 @@ static void save_window_size () static void restore_window_size () { + int dpi = audgui_get_dpi (); int x = aud_get_int ("gtkui", "player_x"); int y = aud_get_int ("gtkui", "player_y"); int w = aud_get_int ("gtkui", "player_width"); int h = aud_get_int ("gtkui", "player_height"); + if (w < 1) + w = 8 * dpi; + if (h < 1) + h = 5 * dpi; + gtk_window_set_default_size ((GtkWindow *) window, w, h); if (x > -1000 && y > -1000) @@ -205,13 +210,9 @@ void clear_ab_repeat () aud_drct_set_ab_repeat (-1, -1); } -static gboolean title_change_cb () +static void title_change (void * = nullptr) { - if (delayed_title_change_source) - { - g_source_remove (delayed_title_change_source); - delayed_title_change_source = 0; - } + delayed_title_change.stop (); if (aud_drct_get_playing ()) { @@ -226,8 +227,6 @@ static gboolean title_change_cb () } else gtk_window_set_title ((GtkWindow *) window, _("Audacious")); - - return false; } void GtkUI::show (bool show) @@ -259,12 +258,12 @@ static void set_time_label (int time, int len) { char s[128] = "<b>"; - if (len && aud_get_bool ("gtkui", "show_remaining_time")) + if (len > 0 && aud_get_bool ("gtkui", "show_remaining_time")) append_str (s, sizeof s, str_format_time (len - time)); else append_str (s, sizeof s, str_format_time (time)); - if (len) + if (len > 0) { append_str (s, sizeof s, " / "); append_str (s, sizeof s, str_format_time (len)); @@ -297,10 +296,10 @@ static void set_slider (int time) gtk_range_set_value ((GtkRange *) slider, time); } -static gboolean time_counter_cb () +static void time_counter_cb (void * = nullptr) { if (slider_is_moving) - return true; + return; slider_seek_time = -1; // delayed reset to avoid seeking twice @@ -311,39 +310,24 @@ static gboolean time_counter_cb () set_slider (time); set_time_label (time, length); - - return true; } static void do_seek (int time) { - int length = aud_drct_get_length (); - time = aud::clamp (time, 0, length); - - set_slider (time); - set_time_label (time, length); aud_drct_seek (time); - - // Trick: Unschedule and then schedule the update function. This gives the - // player 1/4 second to perform the seek before we update the display again, - // in an attempt to reduce flickering. - if (update_song_timeout_source) - { - g_source_remove (update_song_timeout_source); - update_song_timeout_source = g_timeout_add (250, (GSourceFunc) time_counter_cb, nullptr); - } + time_counter_cb (); } static gboolean ui_slider_change_value_cb (GtkRange * range, GtkScrollType scroll, double value) { - int length = aud_drct_get_length (); - int time = aud::clamp ((int) value, 0, length); - - set_time_label (time, length); + int time = value; if (slider_is_moving) + { slider_seek_time = time; + set_time_label (time, aud_drct_get_length ()); + } else if (time != slider_seek_time) // avoid seeking twice do_seek (time); @@ -395,21 +379,19 @@ static void ui_volume_released_cb (GtkButton * button) volume_slider_is_moving = false; } -static gboolean ui_volume_slider_update (void * button) +static void ui_volume_slider_update (void * button) { - if (volume_slider_is_moving || ! button) - return true; + if (volume_slider_is_moving) + return; int volume = aud_drct_get_volume_main (); if (volume == (int) gtk_scale_button_get_value ((GtkScaleButton *) button)) - return true; + return; g_signal_handler_block (button, volume_change_handler_id); gtk_scale_button_set_value ((GtkScaleButton *) button, volume); g_signal_handler_unblock (button, volume_change_handler_id); - - return true; } static void set_slider_length (int length) @@ -440,44 +422,28 @@ static void ui_playback_begin () pause_cb (); gtk_widget_set_sensitive ((GtkWidget *) button_stop, true); - if (delayed_title_change_source) - g_source_remove (delayed_title_change_source); - /* If "title change" is not called by 1/4 second after starting playback, * show "Buffering ..." as the window title. */ - delayed_title_change_source = g_timeout_add (250, (GSourceFunc) - title_change_cb, nullptr); + delayed_title_change.queue (250, title_change, nullptr); } static void ui_playback_ready () { - title_change_cb (); + title_change (); set_slider_length (aud_drct_get_length ()); time_counter_cb (); /* update time counter 4 times a second */ - if (! update_song_timeout_source) - update_song_timeout_source = g_timeout_add (250, (GSourceFunc) - time_counter_cb, nullptr); + timer_add (TimerRate::Hz4, time_counter_cb); gtk_widget_show (label_time); } static void ui_playback_stop () { - if (update_song_timeout_source) - { - g_source_remove (update_song_timeout_source); - update_song_timeout_source = 0; - } - - if (delayed_title_change_source) - g_source_remove (delayed_title_change_source); - - /* Don't update the window title immediately; we may be about to start - * another song. */ - delayed_title_change_source = g_idle_add ((GSourceFunc) title_change_cb, nullptr); + timer_remove (TimerRate::Hz4, time_counter_cb); + title_change (); gtk_tool_button_set_icon_name ((GtkToolButton *) button_play, "media-playback-start"); gtk_widget_set_sensitive ((GtkWidget *) button_stop, false); gtk_widget_hide (slider); @@ -655,7 +621,7 @@ static gboolean playlist_keypress_cb (GtkWidget * widget, GdkEventKey * event) return false; } -static void update_toggles (void * data, void * user) +static void update_toggles (void * = nullptr, void * = nullptr) { gtk_toggle_tool_button_set_active ((GtkToggleToolButton *) button_repeat, aud_get_bool (nullptr, "repeat")); @@ -673,6 +639,28 @@ static void toggle_shuffle (GtkToggleToolButton * button) aud_set_bool (nullptr, "shuffle", gtk_toggle_tool_button_get_active (button)); } +static void toggle_record (GtkToggleToolButton * button) +{ + if (! aud_drct_enable_record (gtk_toggle_tool_button_get_active (button))) + gtk_toggle_tool_button_set_active (button, aud_drct_get_record_enabled ()); +} + +static void record_toggled (void * = nullptr, void * = nullptr) +{ + bool supported = (bool) aud_drct_get_record_plugin (); + bool enabled = aud_drct_get_record_enabled (); + + gtk_widget_set_sensitive ((GtkWidget *) button_record, supported); + gtk_toggle_tool_button_set_active ((GtkToggleToolButton *) button_record, enabled); + + /* update menu item */ + if (enabled != aud_get_bool ("gtkui", "record")) + { + aud_set_bool ("gtkui", "record", enabled); + hook_call ("gtkui set record", nullptr); + } +} + static void toggle_search_tool (GtkToggleToolButton * button) { aud_plugin_enable (search_tool, gtk_toggle_tool_button_get_active (button)); @@ -696,7 +684,7 @@ static void config_save () static void ui_hooks_associate () { - hook_associate ("title change", (HookFunction) title_change_cb, nullptr); + hook_associate ("title change", (HookFunction) title_change, nullptr); hook_associate ("playback begin", (HookFunction) ui_playback_begin, nullptr); hook_associate ("playback ready", (HookFunction) ui_playback_ready, nullptr); hook_associate ("playback pause", (HookFunction) pause_cb, nullptr); @@ -708,12 +696,13 @@ static void ui_hooks_associate () hook_associate ("playlist position", ui_playlist_notebook_position, nullptr); hook_associate ("set shuffle", update_toggles, nullptr); hook_associate ("set repeat", update_toggles, nullptr); + hook_associate ("enable record", record_toggled, nullptr); hook_associate ("config save", (HookFunction) config_save, nullptr); } static void ui_hooks_disassociate () { - hook_dissociate ("title change", (HookFunction) title_change_cb); + hook_dissociate ("title change", (HookFunction) title_change); hook_dissociate ("playback begin", (HookFunction) ui_playback_begin); hook_dissociate ("playback ready", (HookFunction) ui_playback_ready); hook_dissociate ("playback pause", (HookFunction) pause_cb); @@ -725,6 +714,7 @@ static void ui_hooks_disassociate () hook_dissociate ("playlist position", ui_playlist_notebook_position); hook_dissociate ("set shuffle", update_toggles); hook_dissociate ("set repeat", update_toggles); + hook_dissociate ("enable record", record_toggled); hook_dissociate ("config save", (HookFunction) config_save); } @@ -778,9 +768,6 @@ static void remove_dock_plugins () bool GtkUI::init () { - if (aud_get_mainloop_type () != MainloopType::GLib) - return false; - audgui_init (); search_tool = aud_plugin_lookup_basename ("search-tool"); @@ -802,6 +789,7 @@ bool GtkUI::init () toolbar = gtk_toolbar_new (); gtk_toolbar_set_style ((GtkToolbar *) toolbar, GTK_TOOLBAR_ICONS); + gtk_toolbar_set_show_arrow ((GtkToolbar *) toolbar, false); gtk_box_pack_start ((GtkBox *) vbox_outer, toolbar, false, false, 0); /* search button */ @@ -817,10 +805,12 @@ bool GtkUI::init () /* playback buttons */ toolbar_button_add (toolbar, button_open_pressed, "document-open"); toolbar_button_add (toolbar, button_add_pressed, "list-add"); - button_play = toolbar_button_add (toolbar, aud_drct_play_pause, "media-playback-start"); - button_stop = toolbar_button_add (toolbar, aud_drct_stop, "media-playback-stop"); toolbar_button_add (toolbar, aud_drct_pl_prev, "media-skip-backward"); toolbar_button_add (toolbar, aud_drct_pl_next, "media-skip-forward"); + button_play = toolbar_button_add (toolbar, aud_drct_play_pause, "media-playback-start"); + button_stop = toolbar_button_add (toolbar, aud_drct_stop, "media-playback-stop"); + button_record = toggle_button_new ("media-record", toggle_record); + gtk_toolbar_insert ((GtkToolbar *) toolbar, button_record, -1); /* time slider and label */ GtkToolItem * boxitem1 = gtk_tool_item_new (); @@ -832,7 +822,7 @@ bool GtkUI::init () slider = gtk_hscale_new (nullptr); gtk_scale_set_draw_value ((GtkScale *) slider, false); - gtk_widget_set_size_request (slider, 120, -1); + gtk_widget_set_size_request (slider, audgui_get_dpi () * 5 / 4, -1); gtk_widget_set_can_focus (slider, false); gtk_box_pack_start ((GtkBox *) box1, slider, true, true, 6); @@ -898,7 +888,8 @@ bool GtkUI::init () volume_change_handler_id = g_signal_connect (volume, "value-changed", (GCallback) ui_volume_value_changed_cb, nullptr); g_signal_connect (volume, "pressed", (GCallback) ui_volume_pressed_cb, nullptr); g_signal_connect (volume, "released", (GCallback) ui_volume_released_cb, nullptr); - update_volume_timeout_source = g_timeout_add (250, (GSourceFunc) ui_volume_slider_update, volume); + + timer_add (TimerRate::Hz4, ui_volume_slider_update, volume); g_signal_connect (window, "map-event", (GCallback) window_mapped_cb, nullptr); g_signal_connect (window, "delete-event", (GCallback) window_delete, nullptr); @@ -914,11 +905,12 @@ bool GtkUI::init () else ui_playback_stop (); - title_change_cb (); + title_change (); - gtk_widget_show_all (vbox_outer); + update_toggles (); + record_toggled (); - update_toggles (nullptr, nullptr); + gtk_widget_show_all (vbox_outer); menu_rclick = make_menu_rclick (accel); menu_tab = make_menu_tab (accel); @@ -938,23 +930,9 @@ void GtkUI::cleanup () gtk_widget_destroy (menu_rclick); gtk_widget_destroy (menu_tab); - if (update_song_timeout_source) - { - g_source_remove (update_song_timeout_source); - update_song_timeout_source = 0; - } - - if (update_volume_timeout_source) - { - g_source_remove (update_volume_timeout_source); - update_volume_timeout_source = 0; - } - - if (delayed_title_change_source) - { - g_source_remove (delayed_title_change_source); - delayed_title_change_source = 0; - } + timer_remove (TimerRate::Hz4, time_counter_cb); + timer_remove (TimerRate::Hz4, ui_volume_slider_update); + delayed_title_change.stop (); ui_hooks_disassociate (); diff --git a/src/gtkui/ui_infoarea.cc b/src/gtkui/ui_infoarea.cc index d3c9bc8..012349f 100644 --- a/src/gtkui/ui_infoarea.cc +++ b/src/gtkui/ui_infoarea.cc @@ -29,15 +29,25 @@ #include "ui_infoarea.h" -#define SPACING 8 -#define ICON_SIZE 64 -#define HEIGHT (ICON_SIZE + 2 * SPACING) - #define VIS_BANDS 12 -#define VIS_WIDTH (8 * VIS_BANDS - 2) -#define VIS_CENTER (ICON_SIZE * 5 / 8 + SPACING) #define VIS_DELAY 2 /* delay before falloff in frames */ -#define VIS_FALLOFF 2 /* falloff in pixels per frame */ +#define VIS_FALLOFF 2 /* falloff in decibels per frame */ + +int SPACING, ICON_SIZE, HEIGHT, BAND_WIDTH, BAND_SPACING, VIS_WIDTH, VIS_SCALE, VIS_CENTER; + +static void compute_sizes () +{ + int dpi = audgui_get_dpi (); + + SPACING = aud::rescale (dpi, 12, 1); + ICON_SIZE = aud::rescale (dpi, 3, 2); + HEIGHT = ICON_SIZE + 2 * SPACING; + BAND_WIDTH = aud::rescale (dpi, 16, 1); + BAND_SPACING = aud::rescale (dpi, 48, 1); + VIS_WIDTH = VIS_BANDS * (BAND_WIDTH + BAND_SPACING) - BAND_SPACING; + VIS_SCALE = aud::rescale (ICON_SIZE, 8, 5); + VIS_CENTER = VIS_SCALE + SPACING; +} typedef struct { GtkWidget * box, * main; @@ -47,7 +57,6 @@ typedef struct { float alpha, last_alpha; bool stopped; - int fade_timeout; GdkPixbuf * pb, * last_pb; } UIInfoArea; @@ -59,7 +68,7 @@ public: Visualizer (Freq) {} GtkWidget * widget = nullptr; - char bars[VIS_BANDS] {}; + float bars[VIS_BANDS] {}; char delay[VIS_BANDS] {}; void clear (); @@ -97,8 +106,7 @@ void InfoAreaVis::render_freq (const float * freq) } /* 40 dB range */ - int x = 40 + 20 * log10f (n); - x = aud::clamp (x, 0, 40); + float x = 40 + 20 * log10f (n); bars[i] -= aud::max (0, VIS_FALLOFF - delay[i]); @@ -240,10 +248,7 @@ static void get_color (GtkWidget * widget, int i, float * r, float * g, float * rgb_to_hsv (c->red / 65535.0, c->green / 65535.0, c->blue / 65535.0, & h, & s, & v); if (s < 0.1) /* monochrome theme? use blue instead */ - { h = 5; - s = 0.75; - } s = 1 - 0.9 * i / (VIS_BANDS - 1); v = 0.75 + 0.25 * i / (VIS_BANDS - 1); @@ -259,19 +264,19 @@ static int expose_vis_cb (GtkWidget * widget, GdkEventExpose * event) for (int i = 0; i < VIS_BANDS; i++) { - int x = SPACING + 8 * i; - int t = VIS_CENTER - vis.bars[i]; - int m = aud::min (VIS_CENTER + vis.bars[i], HEIGHT); + int x = SPACING + i * (BAND_WIDTH + BAND_SPACING); + int v = aud::clamp ((int) (vis.bars[i] * VIS_SCALE / 40), 0, VIS_SCALE); + int m = aud::min (VIS_CENTER + v, HEIGHT); float r, g, b; get_color (widget, i, & r, & g, & b); cairo_set_source_rgb (cr, r, g, b); - cairo_rectangle (cr, x, t, 6, VIS_CENTER - t); + cairo_rectangle (cr, x, VIS_CENTER - v, BAND_WIDTH, v); cairo_fill (cr); cairo_set_source_rgb (cr, r * 0.3, g * 0.3, b * 0.3); - cairo_rectangle (cr, x, VIS_CENTER, 6, m - VIS_CENTER); + cairo_rectangle (cr, x, VIS_CENTER, BAND_WIDTH, m - VIS_CENTER); cairo_fill (cr); } @@ -285,13 +290,17 @@ static void draw_album_art (cairo_t * cr) if (area->pb) { - gdk_cairo_set_source_pixbuf (cr, area->pb, SPACING, SPACING); + int left = SPACING + (ICON_SIZE - gdk_pixbuf_get_width (area->pb)) / 2; + int top = SPACING + (ICON_SIZE - gdk_pixbuf_get_height (area->pb)) / 2; + gdk_cairo_set_source_pixbuf (cr, area->pb, left, top); cairo_paint_with_alpha (cr, area->alpha); } if (area->last_pb) { - gdk_cairo_set_source_pixbuf (cr, area->last_pb, SPACING, SPACING); + int left = SPACING + (ICON_SIZE - gdk_pixbuf_get_width (area->last_pb)) / 2; + int top = SPACING + (ICON_SIZE - gdk_pixbuf_get_height (area->last_pb)) / 2; + gdk_cairo_set_source_pixbuf (cr, area->last_pb, left, top); cairo_paint_with_alpha (cr, area->last_alpha); } } @@ -303,7 +312,7 @@ static void draw_title (cairo_t * cr) GtkAllocation alloc; gtk_widget_get_allocation (area->main, & alloc); - int x = ICON_SIZE + SPACING * 2; + int x = HEIGHT; int width = alloc.width - x; if (area->title) @@ -339,29 +348,27 @@ static int expose_cb (GtkWidget * widget, GdkEventExpose * event) return true; } -static gboolean ui_infoarea_do_fade () +static void ui_infoarea_do_fade (void *) { - g_return_val_if_fail (area, false); - gboolean ret = false; + g_return_if_fail (area); + bool done = true; if (aud_drct_get_playing () && area->alpha < 1) { area->alpha += 0.1; - ret = true; + done = false; } if (area->last_alpha > 0) { area->last_alpha -= 0.1; - ret = true; + done = false; } gtk_widget_queue_draw (area->main); - if (! ret) - area->fade_timeout = 0; - - return ret; + if (done) + timer_remove (TimerRate::Hz30, ui_infoarea_do_fade); } static void ui_infoarea_set_title () @@ -398,17 +405,6 @@ static void set_album_art () audgui_pixbuf_scale_within (& area->pb, ICON_SIZE); } -static void album_art_ready () -{ - g_return_if_fail (area); - - if (! aud_drct_get_playing ()) - return; - - set_album_art (); - gtk_widget_queue_draw (area->main); -} - static void infoarea_next () { g_return_if_fail (area); @@ -439,9 +435,7 @@ static void ui_infoarea_playback_start () ui_infoarea_set_title (); set_album_art (); - if (! area->fade_timeout) - area->fade_timeout = g_timeout_add (30, (GSourceFunc) - ui_infoarea_do_fade, area); + timer_add (TimerRate::Hz30, ui_infoarea_do_fade); } static void ui_infoarea_playback_stop () @@ -451,9 +445,7 @@ static void ui_infoarea_playback_stop () infoarea_next (); area->stopped = true; - if (! area->fade_timeout) - area->fade_timeout = g_timeout_add (30, (GSourceFunc) - ui_infoarea_do_fade, area); + timer_add (TimerRate::Hz30, ui_infoarea_do_fade); } static void realize_cb (GtkWidget * widget) @@ -508,13 +500,8 @@ static void destroy_cb (GtkWidget * widget) hook_dissociate ("tuple change", (HookFunction) ui_infoarea_set_title); hook_dissociate ("playback ready", (HookFunction) ui_infoarea_playback_start); hook_dissociate ("playback stop", (HookFunction) ui_infoarea_playback_stop); - hook_dissociate ("current art ready", (HookFunction) album_art_ready); - if (area->fade_timeout) - { - g_source_remove (area->fade_timeout); - area->fade_timeout = 0; - } + timer_remove (TimerRate::Hz30, ui_infoarea_do_fade); if (area->pb) g_object_unref (area->pb); @@ -528,12 +515,14 @@ static void destroy_cb (GtkWidget * widget) GtkWidget * ui_infoarea_new () { g_return_val_if_fail (! area, nullptr); - area = new UIInfoArea (); + compute_sizes (); + + area = new UIInfoArea (); area->box = gtk_hbox_new (false, 0); area->main = gtk_drawing_area_new (); - gtk_widget_set_size_request (area->main, ICON_SIZE + 2 * SPACING, HEIGHT); + gtk_widget_set_size_request (area->main, HEIGHT, HEIGHT); gtk_box_pack_start ((GtkBox *) area->box, area->main, true, true, 0); g_signal_connect (area->main, "expose-event", (GCallback) expose_cb, nullptr); @@ -541,22 +530,16 @@ GtkWidget * ui_infoarea_new () hook_associate ("tuple change", (HookFunction) ui_infoarea_set_title, nullptr); hook_associate ("playback ready", (HookFunction) ui_infoarea_playback_start, nullptr); hook_associate ("playback stop", (HookFunction) ui_infoarea_playback_stop, nullptr); - hook_associate ("current art ready", (HookFunction) album_art_ready, nullptr); g_signal_connect (area->box, "destroy", (GCallback) destroy_cb, nullptr); if (aud_drct_get_ready ()) { - ui_infoarea_playback_start (); + ui_infoarea_set_title (); + set_album_art (); /* skip fade-in */ area->alpha = 1; - - if (area->fade_timeout) - { - g_source_remove (area->fade_timeout); - area->fade_timeout = 0; - } } GtkWidget * frame = gtk_frame_new (nullptr); diff --git a/src/gtkui/ui_playlist_notebook.cc b/src/gtkui/ui_playlist_notebook.cc index dc919cb..8c42e05 100644 --- a/src/gtkui/ui_playlist_notebook.cc +++ b/src/gtkui/ui_playlist_notebook.cc @@ -24,7 +24,6 @@ #include <libaudcore/runtime.h> #include <libaudcore/playlist.h> -#include <libaudcore/plugin.h> #include <libaudcore/audstrings.h> #include <libaudcore/hook.h> #include <libaudgui/list.h> @@ -85,12 +84,6 @@ static void size_allocate_cb (GtkWidget * treeview) } } -static void add_button_cb (GtkButton * button) -{ - aud_playlist_insert (-1); - aud_playlist_set_active (aud_playlist_count () - 1); -} - static void make_add_button (GtkWidget * notebook) { GtkWidget * button = gtk_button_new (); @@ -99,7 +92,7 @@ static void make_add_button (GtkWidget * notebook) ("list-add", GTK_ICON_SIZE_MENU)); gtk_widget_set_can_focus (button, false); - g_signal_connect (button, "clicked", (GCallback) add_button_cb, nullptr); + g_signal_connect (button, "clicked", (GCallback) aud_playlist_new, nullptr); gtk_widget_show_all (button); gtk_notebook_set_action_widget ((GtkNotebook *) notebook, button, GTK_PACK_END); @@ -281,8 +274,6 @@ void start_rename_playlist (int playlist) void ui_playlist_notebook_create_tab (int playlist) { - int position = aud_playlist_get_position (playlist); - GtkWidget * scrollwin = gtk_scrolled_window_new (nullptr, nullptr); GtkAdjustment * vscroll = gtk_scrolled_window_get_vadjustment ((GtkScrolledWindow *) scrollwin); @@ -335,14 +326,13 @@ void ui_playlist_notebook_create_tab (int playlist) g_object_set_data ((GObject *) ebox, "playlist-id", GINT_TO_POINTER (id)); g_object_set_data ((GObject *) treeview, "playlist-id", GINT_TO_POINTER (id)); + int position = aud_playlist_get_position (playlist); if (position >= 0) - { - aud_playlist_select_all (playlist, false); - aud_playlist_entry_set_selected (playlist, position, true); - aud_playlist_set_focus (playlist, position); audgui_list_set_highlight (treeview, position); + + int focus = aud_playlist_get_focus (playlist); + if (focus >= 0) audgui_list_set_focus (treeview, position); - } g_signal_connect (ebox, "button-press-event", (GCallback) tab_button_press_cb, nullptr); g_signal_connect (ebox, "key-press-event", (GCallback) tab_key_press_cb, nullptr); @@ -365,8 +355,9 @@ void ui_playlist_notebook_create_tab (int playlist) void ui_playlist_notebook_populate () { int playlist = aud_playlist_get_active (); + int playlist_count = aud_playlist_count (); - for (int count = 0; count < aud_playlist_count (); count ++) + for (int count = 0; count < playlist_count; count ++) ui_playlist_notebook_create_tab (count); gtk_notebook_set_current_page (UI_PLAYLIST_NOTEBOOK, playlist); diff --git a/src/gtkui/ui_playlist_widget.cc b/src/gtkui/ui_playlist_widget.cc index a95e2ea..6c58192 100644 --- a/src/gtkui/ui_playlist_widget.cc +++ b/src/gtkui/ui_playlist_widget.cc @@ -23,6 +23,7 @@ #include <libaudcore/audstrings.h> #include <libaudcore/i18n.h> +#include <libaudcore/mainloop.h> #include <libaudcore/playlist.h> #include <libaudcore/runtime.h> #include <libaudcore/tuple.h> @@ -86,11 +87,11 @@ static const bool pw_col_label[PW_COLS] = { false // bitrate }; -typedef struct { +struct PlaylistWidgetData { int list; - int popup_source, popup_pos; - bool popup_shown; -} PlaylistWidgetData; + int popup_pos = -1; + QueuedFunc popup_timer; +}; static void set_int_from_tuple (GValue * value, const Tuple & tuple, Tuple::Field field) { @@ -202,14 +203,12 @@ static void get_value (void * user, int row, int column, GValue * value) static bool get_selected (void * user, int row) { - return aud_playlist_entry_get_selected (((PlaylistWidgetData *) user)->list, - row); + return aud_playlist_entry_get_selected (((PlaylistWidgetData *) user)->list, row); } static void set_selected (void * user, int row, bool selected) { - aud_playlist_entry_set_selected (((PlaylistWidgetData *) user)->list, row, - selected); + aud_playlist_entry_set_selected (((PlaylistWidgetData *) user)->list, row, selected); } static void select_all (void * user, bool selected) @@ -248,40 +247,25 @@ static void shift_rows (void * user, int row, int before) aud_playlist_shift (list, row, before - row); } -static gboolean popup_show (PlaylistWidgetData * data) -{ - audgui_infopopup_show (data->list, data->popup_pos); - data->popup_shown = true; - - g_source_remove (data->popup_source); - data->popup_source = 0; - return false; -} - static void popup_hide (PlaylistWidgetData * data) { - if (data->popup_source) - { - g_source_remove (data->popup_source); - data->popup_source = 0; - } - - if (data->popup_shown) - { - audgui_infopopup_hide (); - data->popup_shown = false; - } + audgui_infopopup_hide (); data->popup_pos = -1; + data->popup_timer.stop (); } static void popup_trigger (PlaylistWidgetData * data, int pos) { - popup_hide (data); + audgui_infopopup_hide (); + + auto show_cb = [] (void * data_) { + auto data = (PlaylistWidgetData *) data_; + audgui_infopopup_show (data->list, data->popup_pos); + }; data->popup_pos = pos; - data->popup_source = g_timeout_add (aud_get_int (nullptr, "filepopup_delay") * - 100, (GSourceFunc) popup_show, data); + data->popup_timer.queue (aud_get_int (nullptr, "filepopup_delay") * 100, show_cb, data); } static void mouse_motion (void * user, GdkEventMotion * event, int row) @@ -381,9 +365,6 @@ GtkWidget * ui_playlist_widget_new (int playlist) { PlaylistWidgetData * data = new PlaylistWidgetData; data->list = playlist; - data->popup_source = 0; - data->popup_pos = -1; - data->popup_shown = false; GtkWidget * list = audgui_list_new (& callbacks, data, aud_playlist_entry_count (playlist)); @@ -481,7 +462,7 @@ void ui_playlist_widget_scroll (GtkWidget * widget) /* Only update the info popup if it is already shown or about to be shown; * this makes sure that it doesn't pop up when the Audacious window isn't * even visible. */ - if (row >= 0 && (data->popup_source || data->popup_shown)) + if (row >= 0 && data->popup_pos >= 0) popup_trigger (data, row); else popup_hide (data); diff --git a/src/gtkui/ui_statusbar.cc b/src/gtkui/ui_statusbar.cc index a888eed..f496c8e 100644 --- a/src/gtkui/ui_statusbar.cc +++ b/src/gtkui/ui_statusbar.cc @@ -72,7 +72,7 @@ static void ui_statusbar_info_change (void *, void * label) if (samplerate > 0) { - buf.combine (str_printf ("%d kHz", samplerate / 1000)); + buf.combine (str_printf (_("%d kHz"), samplerate / 1000)); if (bitrate > 0) buf.insert (-1, ", "); } diff --git a/src/hotkey/grab.cc b/src/hotkey/grab.cc index 252051f..10f2fd0 100644 --- a/src/hotkey/grab.cc +++ b/src/hotkey/grab.cc @@ -378,7 +378,7 @@ gboolean setup_filter() gdk_window_add_filter (gdk_screen_get_root_window (gdk_screen_get_default ()), gdk_filter, nullptr); - return TRUE; + return true; } void release_filter() diff --git a/src/hotkey/gui.cc b/src/hotkey/gui.cc index 4f7c413..20af047 100644 --- a/src/hotkey/gui.cc +++ b/src/hotkey/gui.cc @@ -143,16 +143,16 @@ on_entry_key_press_event(GtkWidget * widget, int is_mod; int mod; - if (event->keyval == GDK_Tab) return FALSE; - if (event->keyval == GDK_Escape && ((event->state & ~GDK_LOCK_MASK) == 0)) return FALSE; - if (event->keyval == GDK_Return && ((event->state & ~GDK_LOCK_MASK) == 0)) return FALSE; + if (event->keyval == GDK_Tab) return false; + if (event->keyval == GDK_Escape && ((event->state & ~GDK_LOCK_MASK) == 0)) return false; + if (event->keyval == GDK_Return && ((event->state & ~GDK_LOCK_MASK) == 0)) return false; if (event->keyval == GDK_ISO_Left_Tab) { set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type); - return FALSE; + return false; } - if (event->keyval == GDK_Up && ((event->state & ~GDK_LOCK_MASK) == 0)) return FALSE; - if (event->keyval == GDK_Down && ((event->state & ~GDK_LOCK_MASK) == 0)) return FALSE; + if (event->keyval == GDK_Up && ((event->state & ~GDK_LOCK_MASK) == 0)) return false; + if (event->keyval == GDK_Down && ((event->state & ~GDK_LOCK_MASK) == 0)) return false; mod = 0; is_mod = 0; @@ -182,7 +182,7 @@ on_entry_key_press_event(GtkWidget * widget, } set_keytext(controls->keytext, is_mod ? 0 : event->hardware_keycode, mod, TYPE_KEY); - return TRUE; + return true; } static gboolean @@ -191,10 +191,10 @@ on_entry_key_release_event(GtkWidget * widget, void * user_data) { KeyControls *controls = (KeyControls*) user_data; - if (!gtk_widget_is_focus(widget)) return FALSE; + if (!gtk_widget_is_focus(widget)) return false; set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type); - return TRUE; + return true; } static gboolean @@ -205,7 +205,7 @@ on_entry_button_press_event(GtkWidget * widget, KeyControls *controls = (KeyControls*) user_data; int mod; - if (!gtk_widget_is_focus(widget)) return FALSE; + if (!gtk_widget_is_focus(widget)) return false; mod = 0; if (event->state & GDK_CONTROL_MASK) @@ -236,7 +236,7 @@ on_entry_button_press_event(GtkWidget * widget, gtk_window_set_title(GTK_WINDOW(dialog), _("Binding mouse buttons")); response = gtk_dialog_run(GTK_DIALOG(dialog)); gtk_widget_destroy (dialog); - if (response != GTK_RESPONSE_YES) return TRUE; + if (response != GTK_RESPONSE_YES) return true; } controls->hotkey.key = event->button; @@ -246,7 +246,7 @@ on_entry_button_press_event(GtkWidget * widget, if (controls->next == nullptr) add_callback (nullptr, (void *) controls); - return TRUE; + return true; } static gboolean @@ -257,7 +257,7 @@ on_entry_scroll_event(GtkWidget * widget, KeyControls *controls = (KeyControls*) user_data; int mod; - if (!gtk_widget_is_focus(widget)) return FALSE; + if (!gtk_widget_is_focus(widget)) return false; mod = 0; if (event->state & GDK_CONTROL_MASK) @@ -283,14 +283,14 @@ on_entry_scroll_event(GtkWidget * widget, controls->hotkey.key = 6; else if (event->direction == GDK_SCROLL_RIGHT) controls->hotkey.key = 7; - else return FALSE; + else return false; controls->hotkey.mask = mod; controls->hotkey.type = TYPE_MOUSE; set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type); if (controls->next == nullptr) add_callback (nullptr, (void *) controls); - return TRUE; + return true; } KeyControls* add_event_controls(KeyControls* list, @@ -334,7 +334,7 @@ KeyControls* add_event_controls(KeyControls* list, controls->keytext = gtk_entry_new (); gtk_table_attach_defaults (GTK_TABLE (grid), controls->keytext, 1, 2, row, row + 1); - gtk_editable_set_editable(GTK_EDITABLE(controls->keytext), FALSE); + gtk_editable_set_editable(GTK_EDITABLE(controls->keytext), false); set_keytext(controls->keytext, controls->hotkey.key, controls->hotkey.mask, controls->hotkey.type); @@ -379,30 +379,30 @@ void *make_config_widget () ungrab_keys(); - main_vbox = gtk_vbox_new (FALSE, 4); + main_vbox = gtk_vbox_new (false, 4); alignment = gtk_alignment_new (0.5, 0.5, 1, 1); - gtk_box_pack_start (GTK_BOX (main_vbox), alignment, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (main_vbox), alignment, false, true, 0); gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 4, 0, 0, 0); - hbox = gtk_hbox_new (FALSE, 2); + hbox = gtk_hbox_new (false, 2); gtk_container_add (GTK_CONTAINER (alignment), hbox); image = gtk_image_new_from_icon_name ("dialog-information", GTK_ICON_SIZE_DIALOG); - gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (hbox), image, false, true, 0); label = gtk_label_new (_("Press a key combination inside a text field.\nYou can also bind mouse buttons.")); - gtk_box_pack_start (GTK_BOX (hbox), label, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (hbox), label, true, true, 0); gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5); label = gtk_label_new (nullptr); gtk_label_set_markup (GTK_LABEL (label), _("Hotkeys:")); frame = gtk_frame_new (nullptr); gtk_frame_set_label_widget (GTK_FRAME (frame), label); - gtk_box_pack_start (GTK_BOX (main_vbox), frame, TRUE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (main_vbox), frame, true, true, 0); gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_ETCHED_IN); alignment = gtk_alignment_new (0, 0, 1, 0); gtk_container_add (GTK_CONTAINER (frame), alignment); gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 3, 3, 3, 3); - grid = gtk_table_new (0, 0, FALSE); + grid = gtk_table_new (0, 0, false); gtk_table_set_col_spacings (GTK_TABLE (grid), 2); gtk_container_add (GTK_CONTAINER (alignment), grid); @@ -457,11 +457,11 @@ void *make_config_widget () add_event_controls(current_controls, grid, i, &temphotkey); - hbox = gtk_hbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX (main_vbox), hbox, FALSE, TRUE, 0); + hbox = gtk_hbox_new (false, 0); + gtk_box_pack_start (GTK_BOX (main_vbox), hbox, false, true, 0); button_box = gtk_hbutton_box_new (); - gtk_box_pack_start (GTK_BOX (hbox), button_box, FALSE, TRUE, 0); + gtk_box_pack_start (GTK_BOX (hbox), button_box, false, true, 0); gtk_button_box_set_layout (GTK_BUTTON_BOX (button_box), GTK_BUTTONBOX_START); gtk_box_set_spacing (GTK_BOX (button_box), 4); diff --git a/src/hotkey/plugin.cc b/src/hotkey/plugin.cc index 7c2cc23..1ea4a1a 100644 --- a/src/hotkey/plugin.cc +++ b/src/hotkey/plugin.cc @@ -41,6 +41,7 @@ #include <gdk/gdkx.h> #include <gtk/gtk.h> +#define AUD_PLUGIN_GLIB_ONLY #include <libaudcore/drct.h> #include <libaudcore/hook.h> #include <libaudcore/i18n.h> @@ -86,20 +87,16 @@ const char GlobalHotkeys::about[] = " Jonathan A. Davis <davis@jdhouse.org>,\n" " Jeremy Tan <nsx@nsx.homeip.net>"); -PluginConfig* get_config(void) +PluginConfig* get_config () { return &plugin_cfg; } - /* * plugin activated */ bool GlobalHotkeys::init () { - if (aud_get_mainloop_type () != MainloopType::GLib) - return false; - if (! gtk_init_check (nullptr, nullptr)) { AUDERR ("GTK+ initialization failed.\n"); @@ -126,10 +123,10 @@ gboolean handle_keyevent (EVENT event) if (current_volume) { /* volume is not mute */ - mute = FALSE; + mute = false; } else { /* volume is mute */ - mute = TRUE; + mute = true; } /* mute the playback */ @@ -139,12 +136,12 @@ gboolean handle_keyevent (EVENT event) { volume_static = current_volume; aud_drct_set_volume_main (0); - mute = TRUE; + mute = true; } else { aud_drct_set_volume_main (volume_static); - mute = FALSE; + mute = false; } - return TRUE; + return true; } /* decreace volume */ @@ -154,7 +151,7 @@ gboolean handle_keyevent (EVENT event) { current_volume = old_volume; old_volume = 0; - mute = FALSE; + mute = false; } if ((current_volume -= plugin_cfg.vol_decrement) < 0) @@ -168,7 +165,7 @@ gboolean handle_keyevent (EVENT event) } old_volume = current_volume; - return TRUE; + return true; } /* increase volume */ @@ -178,7 +175,7 @@ gboolean handle_keyevent (EVENT event) { current_volume = old_volume; old_volume = 0; - mute = FALSE; + mute = false; } if ((current_volume += plugin_cfg.vol_increment) > 100) @@ -192,49 +189,49 @@ gboolean handle_keyevent (EVENT event) } old_volume = current_volume; - return TRUE; + return true; } /* play */ if (event == EVENT_PLAY) { aud_drct_play (); - return TRUE; + return true; } /* pause */ if (event == EVENT_PAUSE) { aud_drct_play_pause (); - return TRUE; + return true; } /* stop */ if (event == EVENT_STOP) { aud_drct_stop (); - return TRUE; + return true; } /* prev track */ if (event == EVENT_PREV_TRACK) { aud_drct_pl_prev (); - return TRUE; + return true; } /* next track */ if (event == EVENT_NEXT_TRACK) { aud_drct_pl_next (); - return TRUE; + return true; } /* forward */ if (event == EVENT_FORWARD) { aud_drct_seek (aud_drct_get_time () + 5000); - return TRUE; + return true; } /* backward */ @@ -244,55 +241,55 @@ gboolean handle_keyevent (EVENT event) if (time > 5000) time -= 5000; /* Jump 5s back */ else time = 0; aud_drct_seek (time); - return TRUE; + return true; } /* Open Jump-To-File dialog */ if (event == EVENT_JUMP_TO_FILE && ! aud_get_headless_mode ()) { aud_ui_show_jump_to_song (); - return TRUE; + return true; } /* Toggle Windows */ if (event == EVENT_TOGGLE_WIN && ! aud_get_headless_mode ()) { aud_ui_show (! aud_ui_is_shown ()); - return TRUE; + return true; } /* Show OSD through AOSD plugin*/ if (event == EVENT_SHOW_AOSD) { hook_call("aosd toggle", nullptr); - return TRUE; + return true; } if (event == EVENT_TOGGLE_REPEAT) { aud_set_bool (nullptr, "repeat", ! aud_get_bool (nullptr, "repeat")); - return TRUE; + return true; } if (event == EVENT_TOGGLE_SHUFFLE) { aud_set_bool (nullptr, "shuffle", ! aud_get_bool (nullptr, "shuffle")); - return TRUE; + return true; } if (event == EVENT_TOGGLE_STOP) { aud_set_bool (nullptr, "stop_after_current_song", ! aud_get_bool (nullptr, "stop_after_current_song")); - return TRUE; + return true; } if (event == EVENT_RAISE) { - aud_ui_show (TRUE); - return TRUE; + aud_ui_show (true); + return true; } - return FALSE; + return false; } void add_hotkey(HotkeyConfiguration** pphotkey, KeySym keysym, int mask, int type, EVENT event) @@ -317,7 +314,7 @@ void add_hotkey(HotkeyConfiguration** pphotkey, KeySym keysym, int mask, int typ photkey->type = type; } -void load_defaults (void) +void load_defaults () { HotkeyConfiguration* hotkey; @@ -340,7 +337,7 @@ void load_defaults (void) } /* load plugin configuration */ -void load_config (void) +void load_config () { HotkeyConfiguration *hotkey; int i,max; @@ -391,7 +388,7 @@ void load_config (void) } /* save plugin configuration */ -void save_config (void) +void save_config () { int max; HotkeyConfiguration *hotkey; diff --git a/src/hotkey/plugin.h b/src/hotkey/plugin.h index 673b967..1ef372b 100644 --- a/src/hotkey/plugin.h +++ b/src/hotkey/plugin.h @@ -49,9 +49,9 @@ typedef struct { -void load_config (void); -void save_config (void); -PluginConfig* get_config(void); +void load_config (); +void save_config (); +PluginConfig* get_config (); gboolean handle_keyevent(EVENT event); #endif diff --git a/src/jack-ng/jack-ng.cc b/src/jack-ng/jack-ng.cc index 6564475..f358965 100644 --- a/src/jack-ng/jack-ng.cc +++ b/src/jack-ng/jack-ng.cc @@ -157,9 +157,16 @@ bool JACKOutput::connect_ports (int channels) goto fail; } - for (int i = 0; i < channels; i ++) + // upmix mono to stereo + // for all other arrangements, use a one-to-one mapping + if (channels == 1) + count = aud::min (count, 2); + else + count = aud::min (count, channels); + + for (int i = 0; i < count; i ++) { - if (jack_connect (m_client, jack_port_name (m_ports[i]), ports[i]) != 0) + if (jack_connect (m_client, jack_port_name (m_ports[i % channels]), ports[i]) != 0) { aud_ui_show_error (str_printf (_("Failed to connect to JACK port %s."), ports[i])); goto fail; diff --git a/src/ladspa/plugin.cc b/src/ladspa/plugin.cc index 4b0e07e..df32d5f 100644 --- a/src/ladspa/plugin.cc +++ b/src/ladspa/plugin.cc @@ -30,6 +30,7 @@ #include <libaudcore/audstrings.h> #include <libaudcore/preferences.h> #include <libaudcore/runtime.h> +#include <libaudgui/libaudgui-gtk.h> #include "plugin.h" @@ -423,7 +424,7 @@ static void configure_plugin (LoadedPlugin & loaded) { ControlData & control = plugin.controls[i]; - GtkWidget * hbox = gtk_hbox_new (FALSE, 6); + GtkWidget * hbox = gtk_hbox_new (false, 6); gtk_box_pack_start ((GtkBox *) vbox, hbox, 0, 0, 0); if (control.is_toggle) @@ -469,10 +470,12 @@ static void configure_selected () static void * make_config_widget () { - GtkWidget * vbox = gtk_vbox_new (FALSE, 6); - gtk_widget_set_size_request (vbox, 480, 360); + int dpi = audgui_get_dpi (); - GtkWidget * hbox = gtk_hbox_new (FALSE, 6); + GtkWidget * vbox = gtk_vbox_new (false, 6); + gtk_widget_set_size_request (vbox, 5 * dpi, 4 * dpi); + + GtkWidget * hbox = gtk_hbox_new (false, 6); gtk_box_pack_start ((GtkBox *) vbox, hbox, 0, 0, 0); GtkWidget * label = gtk_label_new (_("Module paths:")); @@ -490,10 +493,10 @@ static void * make_config_widget () GtkWidget * entry = gtk_entry_new (); gtk_box_pack_start ((GtkBox *) hbox, entry, 1, 1, 0); - hbox = gtk_hbox_new (FALSE, 6); + hbox = gtk_hbox_new (false, 6); gtk_box_pack_start ((GtkBox *) vbox, hbox, 1, 1, 0); - GtkWidget * vbox2 = gtk_vbox_new (FALSE, 6); + GtkWidget * vbox2 = gtk_vbox_new (false, 6); gtk_box_pack_start ((GtkBox *) hbox, vbox2, 1, 1, 0); label = gtk_label_new (_("Available plugins:")); @@ -506,13 +509,13 @@ static void * make_config_widget () plugin_list = create_plugin_list (); gtk_container_add ((GtkContainer *) scrolled, plugin_list); - GtkWidget * hbox2 = gtk_hbox_new (FALSE, 6); + GtkWidget * hbox2 = gtk_hbox_new (false, 6); gtk_box_pack_start ((GtkBox *) vbox2, hbox2, 0, 0, 0); GtkWidget * enable_button = gtk_button_new_with_label (_("Enable")); gtk_box_pack_end ((GtkBox *) hbox2, enable_button, 0, 0, 0); - vbox2 = gtk_vbox_new (FALSE, 6); + vbox2 = gtk_vbox_new (false, 6); gtk_box_pack_start ((GtkBox *) hbox, vbox2, 1, 1, 0); label = gtk_label_new (_("Enabled plugins:")); @@ -525,7 +528,7 @@ static void * make_config_widget () loaded_list = create_loaded_list (); gtk_container_add ((GtkContainer *) scrolled, loaded_list); - hbox2 = gtk_hbox_new (FALSE, 6); + hbox2 = gtk_hbox_new (false, 6); gtk_box_pack_start ((GtkBox *) vbox2, hbox2, 0, 0, 0); GtkWidget * disable_button = gtk_button_new_with_label (_("Disable")); diff --git a/src/lirc/lirc.cc b/src/lirc/lirc.cc index d0668df..f37d411 100644 --- a/src/lirc/lirc.cc +++ b/src/lirc/lirc.cc @@ -85,7 +85,7 @@ char track_no[64]; int track_no_pos; int tid; -void init_lirc (void) +void init_lirc () { int flags; @@ -350,6 +350,7 @@ static gboolean lirc_input_callback (GIOChannel * source, GIOCondition condition tid = g_timeout_add (1500, jump_to, nullptr); utf8_title_markup = g_markup_printf_escaped ("%s", track_no); hook_call ("aosd toggle", utf8_title_markup); + g_free (utf8_title_markup); } } else diff --git a/src/lyricwiki-qt/lyricwiki.cc b/src/lyricwiki-qt/lyricwiki.cc index 3719097..a87a100 100644 --- a/src/lyricwiki-qt/lyricwiki.cc +++ b/src/lyricwiki-qt/lyricwiki.cc @@ -21,6 +21,9 @@ #include <glib.h> #include <string.h> +#include <QContextMenuEvent> +#include <QDesktopServices> +#include <QMenu> #include <QTextCursor> #include <QTextDocument> #include <QTextEdit> @@ -30,6 +33,7 @@ #include <libxml/HTMLparser.h> #include <libxml/xpath.h> +#define AUD_PLUGIN_QT_ONLY #include <libaudcore/drct.h> #include <libaudcore/i18n.h> #include <libaudcore/plugin.h> @@ -49,14 +53,24 @@ typedef struct { static LyricsState state; -class LyricWikiQt : public GeneralPlugin { +class TextEdit : public QTextEdit +{ +public: + TextEdit (QWidget * parent = nullptr) : QTextEdit (parent) {} + +protected: + void contextMenuEvent (QContextMenuEvent * event); +}; + +class LyricWikiQt : public GeneralPlugin +{ public: static constexpr PluginInfo info = { - N_("LyricWiki Plugin (Qt)"), + N_("LyricWiki Plugin"), PACKAGE }; - constexpr LyricWikiQt() : GeneralPlugin (info, false) {} + constexpr LyricWikiQt () : GeneralPlugin (info, false) {} void * get_qt_widget (); }; @@ -66,15 +80,15 @@ EXPORT LyricWikiQt aud_plugin_instance; * Suppress libxml warnings, because lyricwiki does not generate anything near * valid HTML. */ -static void libxml_error_handler(void *ctx, const char *msg, ...) +static void libxml_error_handler (void * ctx, const char * msg, ...) { } /* g_free() returned text */ -static char *scrape_lyrics_from_lyricwiki_edit_page(const char *buf, int64_t len) +static char * scrape_lyrics_from_lyricwiki_edit_page (const char * buf, int64_t len) { xmlDocPtr doc; - char *ret = nullptr; + char * ret = nullptr; /* * temporarily set our error-handling functor to our suppression function, @@ -85,70 +99,70 @@ static char *scrape_lyrics_from_lyricwiki_edit_page(const char *buf, int64_t len * the previous error functor, so we just have to set it back to default after * parsing and hope for the best. */ - xmlSetGenericErrorFunc(nullptr, libxml_error_handler); - doc = htmlReadMemory(buf, (int) len, nullptr, "utf-8", (HTML_PARSE_RECOVER | HTML_PARSE_NONET)); - xmlSetGenericErrorFunc(nullptr, nullptr); + xmlSetGenericErrorFunc (nullptr, libxml_error_handler); + doc = htmlReadMemory (buf, (int) len, nullptr, "utf-8", (HTML_PARSE_RECOVER | HTML_PARSE_NONET)); + xmlSetGenericErrorFunc (nullptr, nullptr); - if (doc != nullptr) + if (doc) { xmlXPathContextPtr xpath_ctx = nullptr; xmlXPathObjectPtr xpath_obj = nullptr; xmlNodePtr node = nullptr; - xpath_ctx = xmlXPathNewContext(doc); - if (xpath_ctx == nullptr) + xpath_ctx = xmlXPathNewContext (doc); + if (! xpath_ctx) goto give_up; - xpath_obj = xmlXPathEvalExpression((xmlChar *) "//*[@id=\"wpTextbox1\"]", xpath_ctx); - if (xpath_obj == nullptr) + xpath_obj = xmlXPathEvalExpression ((xmlChar *) "//*[@id=\"wpTextbox1\"]", xpath_ctx); + if (! xpath_obj) goto give_up; - if (!xpath_obj->nodesetval->nodeMax) + if (! xpath_obj->nodesetval->nodeMax) goto give_up; node = xpath_obj->nodesetval->nodeTab[0]; give_up: - if (xpath_obj != nullptr) - xmlXPathFreeObject(xpath_obj); + if (xpath_obj) + xmlXPathFreeObject (xpath_obj); - if (xpath_ctx != nullptr) - xmlXPathFreeContext(xpath_ctx); + if (xpath_ctx) + xmlXPathFreeContext (xpath_ctx); - if (node != nullptr) + if (node) { - xmlChar *lyric = xmlNodeGetContent(node); + xmlChar * lyric = xmlNodeGetContent (node); - if (lyric != nullptr) + if (lyric) { - GMatchInfo *match_info; - GRegex *reg; + GMatchInfo * match_info; + GRegex * reg; reg = g_regex_new ("<(lyrics?)>[[:space:]]*(.*?)[[:space:]]*</\\1>", (GRegexCompileFlags) (G_REGEX_MULTILINE | G_REGEX_DOTALL), (GRegexMatchFlags) 0, nullptr); - g_regex_match(reg, (char *) lyric, G_REGEX_MATCH_NEWLINE_ANY, &match_info); + g_regex_match (reg, (char *) lyric, G_REGEX_MATCH_NEWLINE_ANY, & match_info); - ret = g_match_info_fetch(match_info, 2); - if (!g_utf8_collate(ret, "<!-- PUT LYRICS HERE (and delete this entire line) -->")) + ret = g_match_info_fetch (match_info, 2); + if (! strcmp_nocase (ret, "<!-- PUT LYRICS HERE (and delete this entire line) -->")) { - g_free(ret); - ret = g_strdup(_("No lyrics available")); + g_free (ret); + ret = g_strdup (_("No lyrics available")); } - g_regex_unref(reg); + g_regex_unref (reg); } - xmlFree(lyric); + xmlFree (lyric); } - xmlFreeDoc(doc); + xmlFreeDoc (doc); } return ret; } -static String scrape_uri_from_lyricwiki_search_result(const char *buf, int64_t len) +static String scrape_uri_from_lyricwiki_search_result (const char * buf, int64_t len) { xmlDocPtr doc; String uri; @@ -157,13 +171,13 @@ static String scrape_uri_from_lyricwiki_search_result(const char *buf, int64_t l * workaround buggy lyricwiki search output where it cuts the lyrics * halfway through the UTF-8 symbol resulting in invalid XML. */ - GRegex *reg; + GRegex * reg; reg = g_regex_new ("<(lyrics?)>.*</\\1>", (GRegexCompileFlags) (G_REGEX_MULTILINE | G_REGEX_DOTALL | G_REGEX_UNGREEDY), (GRegexMatchFlags) 0, nullptr); - char *newbuf = g_regex_replace_literal(reg, buf, len, 0, "", G_REGEX_MATCH_NEWLINE_ANY, nullptr); - g_regex_unref(reg); + char * newbuf = g_regex_replace_literal (reg, buf, len, 0, "", G_REGEX_MATCH_NEWLINE_ANY, nullptr); + g_regex_unref (reg); /* * temporarily set our error-handling functor to our suppression function, @@ -174,9 +188,9 @@ static String scrape_uri_from_lyricwiki_search_result(const char *buf, int64_t l * the previous error functor, so we just have to set it back to default after * parsing and hope for the best. */ - xmlSetGenericErrorFunc(nullptr, libxml_error_handler); - doc = xmlParseMemory(newbuf, strlen(newbuf)); - xmlSetGenericErrorFunc(nullptr, nullptr); + xmlSetGenericErrorFunc (nullptr, libxml_error_handler); + doc = xmlParseMemory (newbuf, strlen (newbuf)); + xmlSetGenericErrorFunc (nullptr, nullptr); if (doc != nullptr) { @@ -188,71 +202,106 @@ static String scrape_uri_from_lyricwiki_search_result(const char *buf, int64_t l { if (xmlStrEqual(cur->name, (xmlChar *) "url")) { - xmlChar *lyric; - char *basename; - - lyric = xmlNodeGetContent(cur); - basename = g_path_get_basename((char *) lyric); + auto lyric = (char *) xmlNodeGetContent (cur); - uri = String (str_printf ("http://lyrics.wikia.com/index.php?" - "action=edit&title=%s", basename)); + // If the lyrics are unknown, LyricWiki returns a broken link + // to the edit page. Extract the song ID (artist:title) from + // the URI and recreate a working link. + char * title = strstr (lyric, "title="); + if (title) + { + title += 6; + + // Strip trailing "&action=edit" + char * amp = strchr (title, '&'); + if (amp) + * amp = 0; + + // Spaces get replaced with plus signs for some reason. + str_replace_char (title, '+', ' '); + + // LyricWiki interprets UTF-8 as ISO-8859-1, then "converts" + // it to UTF-8 again. Worse, it will sometimes corrupt only + // the song title in this way while leaving the artist name + // intact. So we have to percent-decode the URI, split the + // two strings apart, repair them separately, and then + // rebuild the URI. + auto strings = str_list_to_index (str_decode_percent (title), ":"); + for (String & s : strings) + { + StringBuf orig_utf8 = str_convert (s, -1, "UTF-8", "ISO-8859-1"); + if (orig_utf8 && g_utf8_validate (orig_utf8, -1, nullptr)) + s = String (orig_utf8); + } + + uri = String (str_printf ("http://lyrics.wikia.com/index.php?" + "action=edit&title=%s", (const char *) str_encode_percent + (index_to_str_list (strings, ":")))); + } + else + { + // Convert normal lyrics link to edit page link + char * slash = strrchr (lyric, '/'); + if (slash) + uri = String (str_printf ("http://lyrics.wikia.com/index.php?" + "action=edit&title=%s", slash + 1)); + } - g_free(basename); - xmlFree(lyric); + xmlFree ((xmlChar *) lyric); } } - xmlFreeDoc(doc); + xmlFreeDoc (doc); } - g_free(newbuf); + g_free (newbuf); return uri; } -static void update_lyrics_window(const char *title, const char *artist, const char *lyrics); +static void update_lyrics_window (const char * title, const char * artist, const char * lyrics); -static void get_lyrics_step_3(const char *uri, const Index<char> &buf, void*) +static void get_lyrics_step_3 (const char * uri, const Index<char> & buf, void *) { - if (!state.uri || strcmp(state.uri, uri)) + if (! state.uri || strcmp (state.uri, uri)) return; - if (!buf.len()) + if (! buf.len ()) { update_lyrics_window (_("Error"), nullptr, str_printf (_("Unable to fetch %s"), uri)); return; } - char *lyrics = scrape_lyrics_from_lyricwiki_edit_page(buf.begin(), buf.len()); + char * lyrics = scrape_lyrics_from_lyricwiki_edit_page (buf.begin (), buf.len ()); - if (!lyrics) + if (! lyrics) { update_lyrics_window (_("Error"), nullptr, str_printf (_("Unable to parse %s"), uri)); return; } - update_lyrics_window(state.title, state.artist, lyrics); + update_lyrics_window (state.title, state.artist, lyrics); - g_free(lyrics); + g_free (lyrics); } -static void get_lyrics_step_2(const char *uri1, const Index<char> &buf, void*) +static void get_lyrics_step_2 (const char * uri1, const Index<char> & buf, void *) { - if (!state.uri || strcmp(state.uri, uri1)) + if (! state.uri || strcmp (state.uri, uri1)) return; - if (!buf.len()) + if (! buf.len ()) { update_lyrics_window (_("Error"), nullptr, str_printf (_("Unable to fetch %s"), uri1)); return; } - String uri = scrape_uri_from_lyricwiki_search_result(buf.begin(), buf.len()); + String uri = scrape_uri_from_lyricwiki_search_result (buf.begin (), buf.len ()); - if (!uri) + if (! uri) { update_lyrics_window (_("Error"), nullptr, str_printf (_("Unable to parse %s"), uri1)); @@ -261,15 +310,15 @@ static void get_lyrics_step_2(const char *uri1, const Index<char> &buf, void*) state.uri = uri; - update_lyrics_window(state.title, state.artist, _("Looking for lyrics ...")); - vfs_async_file_get_contents(uri, get_lyrics_step_3, nullptr); + update_lyrics_window (state.title, state.artist, _("Looking for lyrics ...")); + vfs_async_file_get_contents (uri, get_lyrics_step_3, nullptr); } -static void get_lyrics_step_1(void) +static void get_lyrics_step_1 () { - if(!state.artist || !state.title) + if (! state.artist || ! state.title) { - update_lyrics_window(_("Error"), nullptr, _("Missing song metadata")); + update_lyrics_window (_("Error"), nullptr, _("Missing song metadata")); return; } @@ -280,13 +329,13 @@ static void get_lyrics_step_1(void) "action=lyrics&artist=%s&song=%s&fmt=xml", (const char *) artist_buf, (const char *) title_buf)); - update_lyrics_window(state.title, state.artist, _("Connecting to lyrics.wikia.com ...")); - vfs_async_file_get_contents(state.uri, get_lyrics_step_2, nullptr); + update_lyrics_window (state.title, state.artist, _("Connecting to lyrics.wikia.com ...")); + vfs_async_file_get_contents (state.uri, get_lyrics_step_2, nullptr); } static QTextEdit * textedit; -static void update_lyrics_window(const char *title, const char *artist, const char *lyrics) +static void update_lyrics_window (const char * title, const char * artist, const char * lyrics) { QTextDocument doc; QTextCursor cursor (& doc); @@ -294,34 +343,32 @@ static void update_lyrics_window(const char *title, const char *artist, const ch if (! textedit) return; - cursor.insertHtml (QString ("<big>") + QString (title) + QString ("</big>")); + cursor.insertHtml (QString ("<big><b>") + QString (title) + QString ("</b></big>")); - if (artist != nullptr) + if (artist) { cursor.insertHtml (QString ("<br><i>") + QString (artist) + QString ("</i>")); } - cursor.insertHtml ("<br>"); + cursor.insertHtml ("<br><br>"); cursor.insertText (lyrics); - AUDDBG ("update document <%p>\n", textedit); - textedit->setDocument (doc.clone ()); } -static void lyricwiki_playback_began(void) +static void lyricwiki_playback_began () { /* FIXME: cancel previous VFS requests (not possible with current API) */ - state.filename = aud_drct_get_filename(); + state.filename = aud_drct_get_filename (); - Tuple tuple = aud_drct_get_tuple(); - state.title = tuple.get_str(Tuple::Title); - state.artist = tuple.get_str(Tuple::Artist); + Tuple tuple = aud_drct_get_tuple (); + state.title = tuple.get_str (Tuple::Title); + state.artist = tuple.get_str (Tuple::Artist); state.uri = String (); - get_lyrics_step_1(); + get_lyrics_step_1 (); } static void lw_cleanup (QObject * object = nullptr) @@ -339,7 +386,7 @@ static void lw_cleanup (QObject * object = nullptr) void * LyricWikiQt::get_qt_widget () { - textedit = new QTextEdit; + textedit = new TextEdit; textedit->setReadOnly (true); hook_associate ("tuple change", (HookFunction) lyricwiki_playback_began, nullptr); @@ -348,7 +395,22 @@ void * LyricWikiQt::get_qt_widget () if (aud_drct_get_ready ()) lyricwiki_playback_began (); - QObject::connect (textedit, &QObject::destroyed, lw_cleanup); + QObject::connect (textedit, & QObject::destroyed, lw_cleanup); return textedit; } + +void TextEdit::contextMenuEvent (QContextMenuEvent * event) +{ + if (! state.uri) + return QTextEdit::contextMenuEvent (event); + + QMenu * menu = createStandardContextMenu (); + menu->addSeparator (); + QAction * edit = menu->addAction (_("Edit lyrics ...")); + QObject::connect (edit, & QAction::triggered, [] () { + QDesktopServices::openUrl (QUrl ((const char *) state.uri)); + }); + menu->exec (event->globalPos ()); + delete menu; +} diff --git a/src/lyricwiki/lyricwiki.cc b/src/lyricwiki/lyricwiki.cc index ca7f9f8..3ef5dab 100644 --- a/src/lyricwiki/lyricwiki.cc +++ b/src/lyricwiki/lyricwiki.cc @@ -26,6 +26,7 @@ #include <libxml/HTMLparser.h> #include <libxml/xpath.h> +#define AUD_PLUGIN_GLIB_ONLY #include <libaudcore/drct.h> #include <libaudcore/i18n.h> #include <libaudcore/plugin.h> @@ -61,15 +62,15 @@ static LyricsState state; * Suppress libxml warnings, because lyricwiki does not generate anything near * valid HTML. */ -static void libxml_error_handler(void *ctx, const char *msg, ...) +static void libxml_error_handler (void * ctx, const char * msg, ...) { } /* g_free() returned text */ -static char *scrape_lyrics_from_lyricwiki_edit_page(const char *buf, int64_t len) +static char * scrape_lyrics_from_lyricwiki_edit_page (const char * buf, int64_t len) { xmlDocPtr doc; - char *ret = nullptr; + char * ret = nullptr; /* * temporarily set our error-handling functor to our suppression function, @@ -80,70 +81,70 @@ static char *scrape_lyrics_from_lyricwiki_edit_page(const char *buf, int64_t len * the previous error functor, so we just have to set it back to default after * parsing and hope for the best. */ - xmlSetGenericErrorFunc(nullptr, libxml_error_handler); - doc = htmlReadMemory(buf, (int) len, nullptr, "utf-8", (HTML_PARSE_RECOVER | HTML_PARSE_NONET)); - xmlSetGenericErrorFunc(nullptr, nullptr); + xmlSetGenericErrorFunc (nullptr, libxml_error_handler); + doc = htmlReadMemory (buf, (int) len, nullptr, "utf-8", (HTML_PARSE_RECOVER | HTML_PARSE_NONET)); + xmlSetGenericErrorFunc (nullptr, nullptr); - if (doc != nullptr) + if (doc) { xmlXPathContextPtr xpath_ctx = nullptr; xmlXPathObjectPtr xpath_obj = nullptr; xmlNodePtr node = nullptr; - xpath_ctx = xmlXPathNewContext(doc); - if (xpath_ctx == nullptr) + xpath_ctx = xmlXPathNewContext (doc); + if (! xpath_ctx) goto give_up; - xpath_obj = xmlXPathEvalExpression((xmlChar *) "//*[@id=\"wpTextbox1\"]", xpath_ctx); - if (xpath_obj == nullptr) + xpath_obj = xmlXPathEvalExpression ((xmlChar *) "//*[@id=\"wpTextbox1\"]", xpath_ctx); + if (! xpath_obj) goto give_up; - if (!xpath_obj->nodesetval->nodeMax) + if (! xpath_obj->nodesetval->nodeMax) goto give_up; node = xpath_obj->nodesetval->nodeTab[0]; give_up: - if (xpath_obj != nullptr) - xmlXPathFreeObject(xpath_obj); + if (xpath_obj) + xmlXPathFreeObject (xpath_obj); - if (xpath_ctx != nullptr) - xmlXPathFreeContext(xpath_ctx); + if (xpath_ctx) + xmlXPathFreeContext (xpath_ctx); - if (node != nullptr) + if (node) { - xmlChar *lyric = xmlNodeGetContent(node); + xmlChar * lyric = xmlNodeGetContent (node); - if (lyric != nullptr) + if (lyric) { - GMatchInfo *match_info; - GRegex *reg; + GMatchInfo * match_info; + GRegex * reg; reg = g_regex_new ("<(lyrics?)>[[:space:]]*(.*?)[[:space:]]*</\\1>", (GRegexCompileFlags) (G_REGEX_MULTILINE | G_REGEX_DOTALL), (GRegexMatchFlags) 0, nullptr); - g_regex_match(reg, (char *) lyric, G_REGEX_MATCH_NEWLINE_ANY, &match_info); + g_regex_match (reg, (char *) lyric, G_REGEX_MATCH_NEWLINE_ANY, & match_info); - ret = g_match_info_fetch(match_info, 2); - if (!g_utf8_collate(ret, "<!-- PUT LYRICS HERE (and delete this entire line) -->")) + ret = g_match_info_fetch (match_info, 2); + if (! strcmp_nocase (ret, "<!-- PUT LYRICS HERE (and delete this entire line) -->")) { - g_free(ret); - ret = g_strdup(_("No lyrics available")); + g_free (ret); + ret = g_strdup (_("No lyrics available")); } - g_regex_unref(reg); + g_regex_unref (reg); } - xmlFree(lyric); + xmlFree (lyric); } - xmlFreeDoc(doc); + xmlFreeDoc (doc); } return ret; } -static String scrape_uri_from_lyricwiki_search_result(const char *buf, int64_t len) +static String scrape_uri_from_lyricwiki_search_result (const char * buf, int64_t len) { xmlDocPtr doc; String uri; @@ -152,13 +153,13 @@ static String scrape_uri_from_lyricwiki_search_result(const char *buf, int64_t l * workaround buggy lyricwiki search output where it cuts the lyrics * halfway through the UTF-8 symbol resulting in invalid XML. */ - GRegex *reg; + GRegex * reg; reg = g_regex_new ("<(lyrics?)>.*</\\1>", (GRegexCompileFlags) (G_REGEX_MULTILINE | G_REGEX_DOTALL | G_REGEX_UNGREEDY), (GRegexMatchFlags) 0, nullptr); - char *newbuf = g_regex_replace_literal(reg, buf, len, 0, "", G_REGEX_MATCH_NEWLINE_ANY, nullptr); - g_regex_unref(reg); + char * newbuf = g_regex_replace_literal (reg, buf, len, 0, "", G_REGEX_MATCH_NEWLINE_ANY, nullptr); + g_regex_unref (reg); /* * temporarily set our error-handling functor to our suppression function, @@ -169,9 +170,9 @@ static String scrape_uri_from_lyricwiki_search_result(const char *buf, int64_t l * the previous error functor, so we just have to set it back to default after * parsing and hope for the best. */ - xmlSetGenericErrorFunc(nullptr, libxml_error_handler); - doc = xmlParseMemory(newbuf, strlen(newbuf)); - xmlSetGenericErrorFunc(nullptr, nullptr); + xmlSetGenericErrorFunc (nullptr, libxml_error_handler); + doc = xmlParseMemory (newbuf, strlen (newbuf)); + xmlSetGenericErrorFunc (nullptr, nullptr); if (doc != nullptr) { @@ -183,88 +184,124 @@ static String scrape_uri_from_lyricwiki_search_result(const char *buf, int64_t l { if (xmlStrEqual(cur->name, (xmlChar *) "url")) { - xmlChar *lyric; - char *basename; - - lyric = xmlNodeGetContent(cur); - basename = g_path_get_basename((char *) lyric); + auto lyric = (char *) xmlNodeGetContent (cur); - uri = String (str_printf ("http://lyrics.wikia.com/index.php?" - "action=edit&title=%s", basename)); + // If the lyrics are unknown, LyricWiki returns a broken link + // to the edit page. Extract the song ID (artist:title) from + // the URI and recreate a working link. + char * title = strstr (lyric, "title="); + if (title) + { + title += 6; + + // Strip trailing "&action=edit" + char * amp = strchr (title, '&'); + if (amp) + * amp = 0; + + // Spaces get replaced with plus signs for some reason. + str_replace_char (title, '+', ' '); + + // LyricWiki interprets UTF-8 as ISO-8859-1, then "converts" + // it to UTF-8 again. Worse, it will sometimes corrupt only + // the song title in this way while leaving the artist name + // intact. So we have to percent-decode the URI, split the + // two strings apart, repair them separately, and then + // rebuild the URI. + auto strings = str_list_to_index (str_decode_percent (title), ":"); + for (String & s : strings) + { + StringBuf orig_utf8 = str_convert (s, -1, "UTF-8", "ISO-8859-1"); + if (orig_utf8 && g_utf8_validate (orig_utf8, -1, nullptr)) + s = String (orig_utf8); + } + + uri = String (str_printf ("http://lyrics.wikia.com/index.php?" + "action=edit&title=%s", (const char *) str_encode_percent + (index_to_str_list (strings, ":")))); + } + else + { + // Convert normal lyrics link to edit page link + char * slash = strrchr (lyric, '/'); + if (slash) + uri = String (str_printf ("http://lyrics.wikia.com/index.php?" + "action=edit&title=%s", slash + 1)); + } - g_free(basename); - xmlFree(lyric); + xmlFree ((xmlChar *) lyric); } } - xmlFreeDoc(doc); + xmlFreeDoc (doc); } - g_free(newbuf); + g_free (newbuf); return uri; } -static void update_lyrics_window(const char *title, const char *artist, const char *lyrics); +static void update_lyrics_window (const char * title, const char * artist, + const char * lyrics, bool edit_enabled); -static void get_lyrics_step_3(const char *uri, const Index<char> &buf, void*) +static void get_lyrics_step_3 (const char * uri, const Index<char> & buf, void *) { - if (!state.uri || strcmp(state.uri, uri)) + if (! state.uri || strcmp (state.uri, uri)) return; - if (!buf.len()) + if (! buf.len ()) { update_lyrics_window (_("Error"), nullptr, - str_printf (_("Unable to fetch %s"), uri)); + str_printf (_("Unable to fetch %s"), uri), true); return; } - char *lyrics = scrape_lyrics_from_lyricwiki_edit_page(buf.begin(), buf.len()); + char * lyrics = scrape_lyrics_from_lyricwiki_edit_page (buf.begin (), buf.len ()); - if (!lyrics) + if (! lyrics) { update_lyrics_window (_("Error"), nullptr, - str_printf (_("Unable to parse %s"), uri)); + str_printf (_("Unable to parse %s"), uri), true); return; } - update_lyrics_window(state.title, state.artist, lyrics); + update_lyrics_window (state.title, state.artist, lyrics, true); - g_free(lyrics); + g_free (lyrics); } -static void get_lyrics_step_2(const char *uri1, const Index<char> &buf, void*) +static void get_lyrics_step_2 (const char * uri1, const Index<char> & buf, void *) { - if (!state.uri || strcmp(state.uri, uri1)) + if (! state.uri || strcmp(state.uri, uri1)) return; - if (!buf.len()) + if (! buf.len ()) { update_lyrics_window (_("Error"), nullptr, - str_printf (_("Unable to fetch %s"), uri1)); + str_printf (_("Unable to fetch %s"), uri1), false); return; } - String uri = scrape_uri_from_lyricwiki_search_result(buf.begin(), buf.len()); + String uri = scrape_uri_from_lyricwiki_search_result (buf.begin (), buf.len ()); - if (!uri) + if (! uri) { update_lyrics_window (_("Error"), nullptr, - str_printf (_("Unable to parse %s"), uri1)); + str_printf (_("Unable to parse %s"), uri1), false); return; } state.uri = uri; - update_lyrics_window(state.title, state.artist, _("Looking for lyrics ...")); - vfs_async_file_get_contents(uri, get_lyrics_step_3, nullptr); + update_lyrics_window (state.title, state.artist, _("Looking for lyrics ..."), true); + vfs_async_file_get_contents (uri, get_lyrics_step_3, nullptr); } -static void get_lyrics_step_1(void) +static void get_lyrics_step_1 () { - if(!state.artist || !state.title) + if (! state.artist || ! state.title) { - update_lyrics_window(_("Error"), nullptr, _("Missing song metadata")); + update_lyrics_window (_("Error"), nullptr, _("Missing song metadata"), false); return; } @@ -275,86 +312,100 @@ static void get_lyrics_step_1(void) "action=lyrics&artist=%s&song=%s&fmt=xml", (const char *) artist_buf, (const char *) title_buf)); - update_lyrics_window(state.title, state.artist, _("Connecting to lyrics.wikia.com ...")); - vfs_async_file_get_contents(state.uri, get_lyrics_step_2, nullptr); + update_lyrics_window (state.title, state.artist, _("Connecting to lyrics.wikia.com ..."), false); + vfs_async_file_get_contents (state.uri, get_lyrics_step_2, nullptr); } -static GtkWidget *scrollview, *vbox; -static GtkWidget *textview; -static GtkTextBuffer *textbuffer; +static GtkTextView * textview; +static GtkWidget * edit_button; +static GtkTextBuffer * textbuffer; -static GtkWidget *build_widget(void) +static void launch_edit_page () { - textview = gtk_text_view_new(); - gtk_text_view_set_editable(GTK_TEXT_VIEW(textview), FALSE); - gtk_text_view_set_cursor_visible(GTK_TEXT_VIEW(textview), FALSE); - gtk_text_view_set_left_margin(GTK_TEXT_VIEW(textview), 4); - gtk_text_view_set_right_margin(GTK_TEXT_VIEW(textview), 4); - gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(textview), GTK_WRAP_WORD); - textbuffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(textview)); + if (state.uri) + gtk_show_uri (nullptr, state.uri, GDK_CURRENT_TIME, nullptr); +} + +static GtkWidget * build_widget () +{ + textview = (GtkTextView *) gtk_text_view_new (); + gtk_text_view_set_editable (textview, false); + gtk_text_view_set_cursor_visible (textview, false); + gtk_text_view_set_left_margin (textview, 4); + gtk_text_view_set_right_margin (textview, 4); + gtk_text_view_set_wrap_mode (textview, GTK_WRAP_WORD); + textbuffer = gtk_text_view_get_buffer (textview); - scrollview = gtk_scrolled_window_new(nullptr, nullptr); - gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scrollview), GTK_SHADOW_IN); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrollview), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); - vbox = gtk_vbox_new (FALSE, 10); + GtkWidget * scrollview = gtk_scrolled_window_new (nullptr, nullptr); + gtk_scrolled_window_set_shadow_type ((GtkScrolledWindow *) scrollview, GTK_SHADOW_IN); + gtk_scrolled_window_set_policy ((GtkScrolledWindow *) scrollview, GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); + GtkWidget * vbox = gtk_vbox_new (false, 6); - gtk_container_add(GTK_CONTAINER(scrollview), textview); + gtk_container_add ((GtkContainer *) scrollview, (GtkWidget *) textview); + gtk_box_pack_start ((GtkBox *) vbox, scrollview, true, true, 0); - gtk_box_pack_start(GTK_BOX(vbox), scrollview, TRUE, TRUE, 0); + gtk_widget_show_all (vbox); - gtk_widget_show(textview); - gtk_widget_show(scrollview); - gtk_widget_show(vbox); + gtk_text_buffer_create_tag (textbuffer, "weight_bold", "weight", PANGO_WEIGHT_BOLD, nullptr); + gtk_text_buffer_create_tag (textbuffer, "size_x_large", "scale", PANGO_SCALE_X_LARGE, nullptr); + gtk_text_buffer_create_tag (textbuffer, "style_italic", "style", PANGO_STYLE_ITALIC, nullptr); - gtk_text_buffer_create_tag(GTK_TEXT_BUFFER(textbuffer), "weight_bold", "weight", PANGO_WEIGHT_BOLD, nullptr); - gtk_text_buffer_create_tag(GTK_TEXT_BUFFER(textbuffer), "size_x_large", "scale", PANGO_SCALE_X_LARGE, nullptr); - gtk_text_buffer_create_tag(GTK_TEXT_BUFFER(textbuffer), "style_italic", "style", PANGO_STYLE_ITALIC, nullptr); + GtkWidget * hbox = gtk_hbox_new (false, 6); + gtk_box_pack_start ((GtkBox *) vbox, hbox, false, false, 0); + + edit_button = gtk_button_new_with_mnemonic (_("Edit lyrics ...")); + gtk_widget_set_sensitive (edit_button, false); + gtk_box_pack_end ((GtkBox *) hbox, edit_button, false, false, 0); + + g_signal_connect (edit_button, "clicked", (GCallback) launch_edit_page, nullptr); - g_signal_connect (vbox, "destroy", (GCallback) gtk_widget_destroyed, & vbox); return vbox; } -static void update_lyrics_window(const char *title, const char *artist, const char *lyrics) +static void update_lyrics_window (const char * title, const char * artist, + const char * lyrics, bool edit_enabled) { GtkTextIter iter; - if (textbuffer == nullptr) + if (! textbuffer) return; - gtk_text_buffer_set_text(GTK_TEXT_BUFFER(textbuffer), "", -1); + gtk_text_buffer_set_text (textbuffer, "", -1); - gtk_text_buffer_get_start_iter(GTK_TEXT_BUFFER(textbuffer), &iter); + gtk_text_buffer_get_start_iter (textbuffer, & iter); - gtk_text_buffer_insert_with_tags_by_name(GTK_TEXT_BUFFER(textbuffer), &iter, - title, -1, "weight_bold", "size_x_large", nullptr); + gtk_text_buffer_insert_with_tags_by_name (textbuffer, & iter, title, -1, + "weight_bold", "size_x_large", nullptr); - if (artist != nullptr) + if (artist) { - gtk_text_buffer_insert(GTK_TEXT_BUFFER(textbuffer), &iter, "\n", -1); - gtk_text_buffer_insert_with_tags_by_name(GTK_TEXT_BUFFER(textbuffer), - &iter, artist, -1, "style_italic", nullptr); + gtk_text_buffer_insert (textbuffer, & iter, "\n", -1); + gtk_text_buffer_insert_with_tags_by_name (textbuffer, & iter, artist, -1, + "style_italic", nullptr); } - gtk_text_buffer_insert(GTK_TEXT_BUFFER(textbuffer), &iter, "\n\n", -1); - gtk_text_buffer_insert(GTK_TEXT_BUFFER(textbuffer), &iter, lyrics, -1); + gtk_text_buffer_insert (textbuffer, & iter, "\n\n", -1); + gtk_text_buffer_insert (textbuffer, & iter, lyrics, -1); + + gtk_text_buffer_get_start_iter (textbuffer, & iter); + gtk_text_view_scroll_to_iter (textview, & iter, 0, true, 0, 0); - gtk_text_buffer_get_start_iter(GTK_TEXT_BUFFER(textbuffer), &iter); - gtk_text_view_scroll_to_iter(GTK_TEXT_VIEW(textview), &iter, 0, TRUE, 0, 0); + gtk_widget_set_sensitive (edit_button, edit_enabled); } -static void lyricwiki_playback_began(void) +static void lyricwiki_playback_began () { /* FIXME: cancel previous VFS requests (not possible with current API) */ - state.filename = aud_drct_get_filename(); + state.filename = aud_drct_get_filename (); - Tuple tuple = aud_drct_get_tuple(); - state.title = tuple.get_str(Tuple::Title); - state.artist = tuple.get_str(Tuple::Artist); + Tuple tuple = aud_drct_get_tuple (); + state.title = tuple.get_str (Tuple::Title); + state.artist = tuple.get_str (Tuple::Artist); state.uri = String (); - get_lyrics_step_1(); + get_lyrics_step_1 (); } static void destroy_cb () @@ -367,12 +418,14 @@ static void destroy_cb () hook_dissociate ("tuple change", (HookFunction) lyricwiki_playback_began); hook_dissociate ("playback ready", (HookFunction) lyricwiki_playback_began); + textview = nullptr; textbuffer = nullptr; + edit_button = nullptr; } void * LyricWiki::get_gtk_widget () { - build_widget (); + GtkWidget * vbox = build_widget (); hook_associate ("tuple change", (HookFunction) lyricwiki_playback_began, nullptr); hook_associate ("playback ready", (HookFunction) lyricwiki_playback_began, nullptr); diff --git a/src/m3u/m3u.cc b/src/m3u/m3u.cc index 0ce63af..e2ad9d8 100644 --- a/src/m3u/m3u.cc +++ b/src/m3u/m3u.cc @@ -41,47 +41,32 @@ public: EXPORT M3ULoader aud_plugin_instance; -static void strip_char (char * text, char c) -{ - char * set = text; - char a; - - while ((a = * text ++)) - if (a != c) - * set ++ = a; - - * set = 0; -} - -static Index<char> read_win_text (VFSFile & file) -{ - Index<char> raw = file.read_all (); - if (! raw.len ()) - return raw; - - raw.append (0); /* null-terminated */ - strip_char (raw.begin (), '\r'); - return raw; -} - static char * split_line (char * line) { char * feed = strchr (line, '\n'); if (! feed) return nullptr; - * feed = 0; + if (feed > line && feed[-1] == '\r') + feed[-1] = 0; + else + feed[0] = 0; + return feed + 1; } bool M3ULoader::load (const char * path, VFSFile & file, String & title, Index<PlaylistAddItem> & items) { - Index<char> text = read_win_text (file); + Index<char> text = file.read_all (); if (! text.len ()) return false; + text.append (0); /* null-terminate */ + char * parse = text.begin (); + if (! strncmp (parse, "\xef\xbb\xbf", 3)) /* byte order mark */ + parse += 3; while (parse) { diff --git a/src/mixer/mixer.cc b/src/mixer/mixer.cc index 9fe5728..8285278 100644 --- a/src/mixer/mixer.cc +++ b/src/mixer/mixer.cc @@ -137,6 +137,29 @@ static Index<float> & surround_5p1_to_stereo (Index<float> & data) return mixer_buf; } +/* 5 channels case. Quad + center channel */ +static Index<float> & quadro_5_to_stereo (Index<float> & data) +{ + int frames = data.len () / 5; + mixer_buf.resize (2 * frames); + + float * get = data.begin (); + float * set = mixer_buf.begin (); + + while (frames --) + { + float front_left = * get ++; + float front_right = * get ++; + float center = * get ++; + float rear_left = * get ++; + float rear_right = * get ++; + * set ++ = front_left + (center * 0.5) + rear_left; + * set ++ = front_right + (center * 0.5) + rear_right; + } + + return mixer_buf; +} + static Converter get_converter (int in, int out) { if (in == 1 && out == 2) @@ -145,6 +168,8 @@ static Converter get_converter (int in, int out) return stereo_to_mono; if (in == 4 && out == 2) return quadro_to_stereo; + if (in == 5 && out == 2) + return quadro_5_to_stereo; if (in == 6 && out == 2) return surround_5p1_to_stereo; diff --git a/src/modplug/modplugbmp.cc b/src/modplug/modplugbmp.cc index ae8d8b5..8fd269c 100644 --- a/src/modplug/modplugbmp.cc +++ b/src/modplug/modplugbmp.cc @@ -51,6 +51,12 @@ bool ModplugXMMS::is_our_file (const char * filename, VFSFile & file) return true; if (!memcmp(magic, PSM_MAGIC, 4)) return true; + if (!memcmp(magic, MMD0_MAGIC, 4)) + return true; + if (!memcmp(magic, MMD1_MAGIC, 4)) + return true; + if (!memcmp(magic, OKTA_MAGIC, 8)) + return true; if (file.fseek (44, VFS_SEEK_SET)) return false; @@ -58,6 +64,8 @@ bool ModplugXMMS::is_our_file (const char * filename, VFSFile & file) return false; if (!memcmp(magic, S3M_MAGIC, 4)) return true; + if (!memcmp(magic, PTM_MAGIC, 4)) + return true; if (file.fseek (1080, VFS_SEEK_SET)) return false; diff --git a/src/modplug/modplugbmp.h b/src/modplug/modplugbmp.h index c2887ce..e2c4d3c 100644 --- a/src/modplug/modplugbmp.h +++ b/src/modplug/modplugbmp.h @@ -27,6 +27,7 @@ #define MOD_MAGIC_TAKETRACKER32 "32CN" // Taketracker 32 channel #define S3M_MAGIC "SCRM" /* This is the SCRM string at offset 44 to 47 in the S3M header */ +#define PTM_MAGIC "PTMF" /* Same position for Polytracker magic string */ /* These nicer formats have the magic bytes at the front of the file where they belong */ #define UMX_MAGIC "\xC1\x83\x2A\x9E" @@ -35,6 +36,9 @@ #define IT_MAGIC "IMPM" /* IMPM */ #define MTM_MAGIC "\x4D\x54\x4D\x10" #define PSM_MAGIC "PSM " +#define MMD0_MAGIC "MMD0" /* Med MoDule 0 */ +#define MMD1_MAGIC "MMD1" /* OctaMED Professional */ +#define OKTA_MAGIC "OKTASONG" /* Oktalyzer */ class CSoundFile; class Archive; diff --git a/src/modplug/plugin_main.cc b/src/modplug/plugin_main.cc index 6d22ea4..540089e 100644 --- a/src/modplug/plugin_main.cc +++ b/src/modplug/plugin_main.cc @@ -8,6 +8,9 @@ #include "modplugbmp.h" +#include <libmodplug/stdafx.h> +#include <libmodplug/sndfile.h> + #include <libaudcore/runtime.h> #include <libaudcore/preferences.h> @@ -23,7 +26,7 @@ const char * const ModplugXMMS::exts[] = const char * const ModplugXMMS::defaults[] = { "Bits", "16", "Channels", "2", - "ResamplingMode", "3", /* SRCMODE_POLYPHASE */ + "ResamplingMode", aud::numeric_string<SRCMODE_POLYPHASE>::str, "Frequency", "44100", "Reverb", "FALSE", diff --git a/src/mpg123/mpg123.cc b/src/mpg123/mpg123.cc index 4807aec..2855356 100644 --- a/src/mpg123/mpg123.cc +++ b/src/mpg123/mpg123.cc @@ -66,8 +66,7 @@ public: void cleanup (); bool is_our_file (const char * filename, VFSFile & file); - Tuple read_tuple (const char * filename, VFSFile & file); - Index<char> read_image (const char * filename, VFSFile & file); + bool read_tag (const char * filename, VFSFile & file, Tuple * tuple, Index<char> * image); bool write_tuple (const char * filename, VFSFile & file, const Tuple & tuple); bool play (const char * filename, VFSFile & file); }; @@ -123,163 +122,163 @@ void MPG123Plugin::cleanup () mpg123_exit(); } -static void set_format (mpg123_handle * dec) +struct DecodeState { + mpg123_handle * dec = nullptr; + + bool init (const char * filename, VFSFile & file, bool probing, bool stream); + + ~DecodeState() + { mpg123_delete (dec); } + + long rate; + int channels, encoding; + mpg123_frameinfo info; + size_t bytes_read; + float buf[4096]; +}; + +bool DecodeState::init (const char * filename, VFSFile & file, bool probing, bool stream) +{ + dec = mpg123_new (nullptr, nullptr); + mpg123_param (dec, MPG123_ADD_FLAGS, DECODE_OPTIONS, 0); + mpg123_replace_reader_handle (dec, replace_read, + stream ? replace_lseek_dummy : replace_lseek, nullptr); + + /* be strict about junk data in file during content probe */ + if (probing) + mpg123_param (dec, MPG123_RESYNC_LIMIT, 0, 0); + mpg123_format_none (dec); for (int rate : {8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000}) mpg123_format (dec, rate, MPG123_MONO | MPG123_STEREO, MPG123_ENC_FLOAT_32); -} -static void make_format_string (const struct mpg123_frameinfo * info, char * - buf, int bsize) -{ - static const char * vers[] = {"1", "2", "2.5"}; - snprintf (buf, bsize, "MPEG-%s layer %d", vers[info->version], info->layer); -} - -bool MPG123Plugin::is_our_file (const char * fname, VFSFile & file) -{ - /* MPG123 likes to grab WMA streams, so blacklist anything that starts with - * mms://. If there are mms:// streams out there carrying MP3, they will - * just have to play in ffaudio. --jlindgren */ - if (! strncmp (fname, "mms://", 6)) - return false; + if (mpg123_open_handle (dec, & file) < 0) + goto err; - bool is_streaming = (file.fsize () < 0); + if (! stream && aud_get_bool ("mpg123", "full_scan") && mpg123_scan (dec) < 0) + goto err; - /* Some MP3s begin with enormous ID3 tags, which fill up the whole probe - * buffer and thus hide any MP3 content. As a workaround, assume that an - * ID3 tag means an MP3 file. --jlindgren */ - if (! is_streaming) + while (1) { - char id3buf[3]; - if (file.fread (id3buf, 1, 3) != 3) - return false; + if (mpg123_getformat (dec, & rate, & channels, & encoding) < 0) + goto err; - if (! memcmp (id3buf, "ID3", 3)) - return true; + int ret = mpg123_read (dec, (unsigned char *) buf, sizeof buf, & bytes_read); - if (file.fseek (0, VFS_SEEK_SET) < 0) - return false; - } + if (ret == MPG123_NEW_FORMAT) + continue; + if (ret < 0) + goto err; - mpg123_handle * dec = mpg123_new (nullptr, nullptr); - mpg123_param (dec, MPG123_ADD_FLAGS, DECODE_OPTIONS, 0); + if (mpg123_info (dec, & info) < 0) + goto err; - if (is_streaming) - mpg123_replace_reader_handle (dec, replace_read, replace_lseek_dummy, nullptr); - else - mpg123_replace_reader_handle (dec, replace_read, replace_lseek, nullptr); + return dec; + } - set_format (dec); +err: + if (probing) + AUDDBG ("mpg123 error in %s: %s\n", filename, mpg123_strerror (dec)); + else + AUDERR ("mpg123 error in %s: %s\n", filename, mpg123_strerror (dec)); - int res; - if ((res = mpg123_open_handle (dec, & file)) < 0) - { -ERR: - AUDDBG ("Probe error: %s\n", mpg123_plain_strerror (res)); - mpg123_delete (dec); - return false; - } + mpg123_delete (dec); + dec = nullptr; - if (! is_streaming && aud_get_bool ("mpg123", "full_scan") && mpg123_scan (dec) < 0) - goto ERR; + return false; +} -RETRY:; - long rate; - int chan, enc; - if ((res = mpg123_getformat (dec, & rate, & chan, & enc)) < 0) - goto ERR; +// with better buffering in Audacious 3.7, this is now safe for streams +static bool detect_id3 (VFSFile & file) +{ + bool is_id3 = false; + char id3buf[3]; - struct mpg123_frameinfo info; - if ((res = mpg123_info (dec, & info)) < 0) - goto ERR; + if (file.fread (id3buf, 1, 3) == 3) + is_id3 = ! memcmp (id3buf, "ID3", 3); - float out[8192]; - size_t done; - while ((res = mpg123_read (dec, (unsigned char *) out, sizeof out, & done)) < 0) - { - if (res == MPG123_NEW_FORMAT) - goto RETRY; - goto ERR; - } + if (file.fseek (0, VFS_SEEK_SET) < 0) + is_id3 = false; - char str[32]; - make_format_string (& info, str, sizeof str); - AUDDBG ("Accepted as %s: %s.\n", str, fname); + return is_id3; +} - mpg123_delete (dec); - return true; +static StringBuf make_format_string (const mpg123_frameinfo * info) +{ + static const char * vers[] = {"1", "2", "2.5"}; + return str_printf ("MPEG-%s layer %d", vers[info->version], info->layer); } -Tuple MPG123Plugin::read_tuple (const char * filename, VFSFile & file) +bool MPG123Plugin::is_our_file (const char * filename, VFSFile & file) { bool stream = (file.fsize () < 0); - mpg123_handle * decoder = mpg123_new (nullptr, nullptr); - int result; - long rate; - int channels, encoding; - struct mpg123_frameinfo info; - char scratch[32]; - mpg123_param (decoder, MPG123_ADD_FLAGS, DECODE_OPTIONS, 0); + /* Some MP3s begin with enormous ID3 tags, which fill up the whole probe + * buffer and thus hide any MP3 content. As a workaround, assume that an + * ID3 tag means an MP3 file. --jlindgren */ + if (detect_id3 (file)) + return true; - if (stream) - mpg123_replace_reader_handle (decoder, replace_read, replace_lseek_dummy, nullptr); - else - mpg123_replace_reader_handle (decoder, replace_read, replace_lseek, nullptr); + DecodeState s; + if (! s.init (filename, file, true, stream)) + return false; - if ((result = mpg123_open_handle (decoder, & file)) < 0 - || (! stream && aud_get_bool ("mpg123", "full_scan") && (result = mpg123_scan (decoder)) < 0) - || (result = mpg123_getformat (decoder, & rate, & channels, & encoding)) < 0 - || (result = mpg123_info (decoder, & info)) < 0) - { - AUDERR ("mpg123 probe error for %s: %s\n", filename, mpg123_plain_strerror (result)); - mpg123_delete (decoder); - return Tuple (); - } + AUDDBG ("Accepted as %s: %s.\n", (const char *) make_format_string (& s.info), filename); + return true; +} - Tuple tuple; - tuple.set_filename (filename); - make_format_string (& info, scratch, sizeof scratch); - tuple.set_str (Tuple::Codec, scratch); - snprintf (scratch, sizeof scratch, "%s, %d Hz", (channels == 2) - ? _("Stereo") : (channels > 2) ? _("Surround") : _("Mono"), (int) rate); - tuple.set_str (Tuple::Quality, scratch); - tuple.set_int (Tuple::Bitrate, info.bitrate); +static bool read_mpg123_info (const char * filename, VFSFile & file, Tuple & tuple) +{ + int64_t size = file.fsize (); + bool stream = (size < 0); + + DecodeState s; + if (! s.init (filename, file, false, stream)) + return false; + + tuple.set_str (Tuple::Codec, make_format_string (& s.info)); + tuple.set_str (Tuple::Quality, str_printf ("%s, %d Hz", (s.channels == 2) ? + _("Stereo") : (s.channels > 2) ? _("Surround") : _("Mono"), (int) s.rate)); + tuple.set_int (Tuple::Bitrate, s.info.bitrate); if (! stream) { - int64_t size = file.fsize (); - int64_t samples = mpg123_length (decoder); - int length = (samples > 0 && rate > 0) ? samples * 1000 / rate : 0; + int64_t samples = mpg123_length (s.dec); + int length = (s.rate > 0) ? samples * 1000 / s.rate : 0; if (length > 0) + { tuple.set_int (Tuple::Length, length); - if (size > 0 && length > 0) tuple.set_int (Tuple::Bitrate, 8 * size / length); + } } - mpg123_delete (decoder); + return true; +} - if (! stream && ! file.fseek (0, VFS_SEEK_SET)) - audtag::tuple_read (tuple, file); +bool MPG123Plugin::read_tag (const char * filename, VFSFile & file, Tuple * tuple, Index<char> * image) +{ + bool stream = (file.fsize () < 0); - if (stream) - tuple.fetch_stream_info (file); + if (tuple) + { + if (! read_mpg123_info (filename, file, * tuple)) + return false; - return tuple; -} + if (stream) + tuple->fetch_stream_info (file); -typedef struct { - mpg123_handle *decoder; - long rate; - int channels; - int encoding; - bool stream; - Tuple tu; -} MPG123PlaybackContext; + if (! stream && file.fseek (0, VFS_SEEK_SET) != 0) + return false; + } + + if (! stream) + audtag::read_tag (file, tuple, image); + + return true; +} static void print_mpg123_error (const char * filename, mpg123_handle * decoder) { @@ -288,69 +287,30 @@ static void print_mpg123_error (const char * filename, mpg123_handle * decoder) bool MPG123Plugin::play (const char * filename, VFSFile & file) { - bool error = false; - MPG123PlaybackContext ctx; - int ret; - int bitrate = 0, bitrate_sum = 0, bitrate_count = 0; - struct mpg123_frameinfo fi; - int error_count = 0; - - memset(&ctx, 0, sizeof(MPG123PlaybackContext)); - memset(&fi, 0, sizeof(struct mpg123_frameinfo)); - - AUDDBG("playback worker started for %s\n", filename); - - AUDDBG ("Checking for streaming ...\n"); - ctx.stream = (file.fsize () < 0); - ctx.tu = ctx.stream ? get_playback_tuple () : Tuple (); - - ctx.decoder = mpg123_new (nullptr, nullptr); - mpg123_param (ctx.decoder, MPG123_ADD_FLAGS, DECODE_OPTIONS, 0); - - if (ctx.stream) - mpg123_replace_reader_handle (ctx.decoder, replace_read, replace_lseek_dummy, nullptr); - else - mpg123_replace_reader_handle (ctx.decoder, replace_read, replace_lseek, nullptr); - - set_format (ctx.decoder); - - float outbuf[8192]; - size_t outbuf_size = 0; + bool stream = (file.fsize () < 0); - if (mpg123_open_handle (ctx.decoder, & file) < 0) + Tuple tuple; + if (stream) { -OPEN_ERROR: - print_mpg123_error (filename, ctx.decoder); - error = true; - goto cleanup; + tuple = get_playback_tuple (); + if (detect_id3 (file) && audtag::read_tag (file, & tuple, nullptr)) + set_playback_tuple (tuple.ref ()); } - if (! ctx.stream && aud_get_bool ("mpg123", "full_scan") && mpg123_scan (ctx.decoder) < 0) - goto OPEN_ERROR; - -GET_FORMAT: - if (mpg123_getformat (ctx.decoder, & ctx.rate, & ctx.channels, - & ctx.encoding) < 0) - goto OPEN_ERROR; - - while ((ret = mpg123_read (ctx.decoder, (unsigned char *) outbuf, - sizeof outbuf, & outbuf_size)) < 0) - { - if (ret == MPG123_NEW_FORMAT) - goto GET_FORMAT; - goto OPEN_ERROR; - } + DecodeState s; + if (! s.init (filename, file, false, stream)) + return false; - if (mpg123_info (ctx.decoder, & fi) < 0) - goto OPEN_ERROR; + int bitrate = s.info.bitrate * 1000; + int bitrate_sum = 0, bitrate_count = 0; + int error_count = 0; - bitrate = fi.bitrate * 1000; set_stream_bitrate (bitrate); - if (ctx.tu && ctx.tu.fetch_stream_info (file)) - set_playback_tuple (ctx.tu.ref ()); + if (tuple && tuple.fetch_stream_info (file)) + set_playback_tuple (tuple.ref ()); - open_audio (FMT_FLOAT, ctx.rate, ctx.channels); + open_audio (FMT_FLOAT, s.rate, s.channels); while (! check_stop ()) { @@ -358,14 +318,14 @@ GET_FORMAT: if (seek >= 0) { - if (mpg123_seek (ctx.decoder, (int64_t) seek * ctx.rate / 1000, SEEK_SET) < 0) - print_mpg123_error (filename, ctx.decoder); + if (mpg123_seek (s.dec, (int64_t) seek * s.rate / 1000, SEEK_SET) < 0) + print_mpg123_error (filename, s.dec); - outbuf_size = 0; + s.bytes_read = 0; } - mpg123_info(ctx.decoder, &fi); - bitrate_sum += fi.bitrate; + mpg123_info (s.dec, & s.info); + bitrate_sum += s.info.bitrate; bitrate_count ++; if (bitrate_sum / bitrate_count != bitrate && bitrate_count >= 16) @@ -376,35 +336,35 @@ GET_FORMAT: bitrate_count = 0; } - if (ctx.tu && ctx.tu.fetch_stream_info (file)) - set_playback_tuple (ctx.tu.ref ()); + if (tuple && tuple.fetch_stream_info (file)) + set_playback_tuple (tuple.ref ()); - if (! outbuf_size && (ret = mpg123_read (ctx.decoder, - (unsigned char *) outbuf, sizeof outbuf, & outbuf_size)) < 0) + if (! s.bytes_read) { + int ret = mpg123_read (s.dec, (unsigned char *) s.buf, sizeof s.buf, & s.bytes_read); + if (ret == MPG123_DONE || ret == MPG123_ERR_READER) break; - print_mpg123_error (filename, ctx.decoder); - - if (++ error_count >= 10) + if (ret < 0) { - error = true; - break; + print_mpg123_error (filename, s.dec); + + if (++ error_count >= 10) + return false; } } - else + + if (s.bytes_read) { error_count = 0; - write_audio (outbuf, outbuf_size); - outbuf_size = 0; + write_audio (s.buf, s.bytes_read); + s.bytes_read = 0; } } -cleanup: - mpg123_delete(ctx.decoder); - return ! error; + return true; } bool MPG123Plugin::write_tuple (const char * filename, VFSFile & file, const Tuple & tuple) @@ -415,12 +375,4 @@ bool MPG123Plugin::write_tuple (const char * filename, VFSFile & file, const Tup return audtag::tuple_write (tuple, file, audtag::TagType::ID3v2); } -Index<char> MPG123Plugin::read_image (const char * filename, VFSFile & file) -{ - if (file.fsize () < 0) // stream? - return Index<char> (); - - return audtag::image_read (file); -} - const char * const MPG123Plugin::exts[] = { "mp3", "mp2", "mp1", "bmu", nullptr }; diff --git a/src/mpris2/plugin.cc b/src/mpris2/plugin.cc index 95f592b..833cc62 100644 --- a/src/mpris2/plugin.cc +++ b/src/mpris2/plugin.cc @@ -24,7 +24,6 @@ #include <libaudcore/hook.h> #include <libaudcore/i18n.h> #include <libaudcore/interface.h> -#include <libaudcore/playlist.h> #include <libaudcore/plugin.h> #include <libaudcore/probe.h> #include <libaudcore/runtime.h> @@ -52,8 +51,6 @@ static GObject * object_core, * object_player; static String last_title, last_artist, last_album, last_file; static int last_length; static const char * image_file; -static gboolean recheck_image; -static int update_timer; static gboolean quit_cb (MprisMediaPlayer2 * object, GDBusMethodInvocation * call, void * unused) @@ -76,31 +73,27 @@ static void update_metadata (void * data, GObject * object) String title, artist, album, file; int length = 0; - int playlist = aud_playlist_get_playing (); - int entry = (playlist >= 0) ? aud_playlist_get_position (playlist) : -1; - - if (entry >= 0) + if (aud_drct_get_ready ()) { - Tuple tuple = aud_playlist_entry_get_tuple (playlist, entry, Playlist::Guess); + Tuple tuple = aud_drct_get_tuple (); title = tuple.get_str (Tuple::Title); artist = tuple.get_str (Tuple::Artist); album = tuple.get_str (Tuple::Album); length = tuple.get_int (Tuple::Length); - file = aud_playlist_entry_get_filename (playlist, entry); + file = aud_drct_get_filename (); } if (title == last_title && artist == last_artist && album == last_album - && file == last_file && length == last_length && ! recheck_image) + && file == last_file && length == last_length) return; - if (file != last_file || recheck_image) + if (file != last_file) { if (image_file) aud_art_unref (last_file); image_file = file ? aud_art_request_file (file) : nullptr; - recheck_image = false; } last_title = title; @@ -170,12 +163,6 @@ static void update_metadata (void * data, GObject * object) g_object_set (object, "metadata", array, nullptr); } -static void update_image (void * data, GObject * object) -{ - recheck_image = true; - update_metadata (data, object); -} - static void volume_changed (GObject * object) { double vol; @@ -183,7 +170,7 @@ static void volume_changed (GObject * object) aud_drct_set_volume_main (round (vol * 100)); } -static gboolean update (GObject * object) +static void update (void * object) { int64_t pos = 0; int vol = 0; @@ -194,9 +181,8 @@ static gboolean update (GObject * object) vol = aud_drct_get_volume_main (); g_signal_handlers_block_by_func (object, (void *) volume_changed, nullptr); - g_object_set (object, "position", pos, "volume", (double) vol / 100, nullptr); + g_object_set ((GObject *) object, "position", pos, "volume", (double) vol / 100, nullptr); g_signal_handlers_unblock_by_func (object, (void *) volume_changed, nullptr); - return true; } static void update_playback_status (void * data, GObject * object) @@ -294,20 +280,14 @@ void MPRIS2Plugin::cleanup () hook_dissociate ("playback stop", (HookFunction) update_playback_status); hook_dissociate ("playback unpause", (HookFunction) update_playback_status); - hook_dissociate ("playlist set playing", (HookFunction) update_metadata); - hook_dissociate ("playlist position", (HookFunction) update_metadata); - hook_dissociate ("playlist update", (HookFunction) update_metadata); - - hook_dissociate ("current art ready", (HookFunction) update_image); + hook_dissociate ("playback ready", (HookFunction) update_metadata); + hook_dissociate ("playback stop", (HookFunction) update_metadata); + hook_dissociate ("tuple change", (HookFunction) update_metadata); hook_dissociate ("playback ready", (HookFunction) emit_seek); hook_dissociate ("playback seek", (HookFunction) emit_seek); - if (update_timer) - { - g_source_remove (update_timer); - update_timer = 0; - } + timer_remove (TimerRate::Hz4, update, object_player); g_object_unref (object_core); g_object_unref (object_player); @@ -367,7 +347,6 @@ bool MPRIS2Plugin::init () "can-seek", (gboolean) true, nullptr); - update_timer = g_timeout_add (250, (GSourceFunc) update, object_player); update_playback_status (nullptr, object_player); if (aud_drct_get_playing () && aud_drct_get_ready ()) @@ -378,15 +357,15 @@ bool MPRIS2Plugin::init () hook_associate ("playback stop", (HookFunction) update_playback_status, object_player); hook_associate ("playback unpause", (HookFunction) update_playback_status, object_player); - hook_associate ("playlist set playing", (HookFunction) update_metadata, object_player); - hook_associate ("playlist position", (HookFunction) update_metadata, object_player); - hook_associate ("playlist update", (HookFunction) update_metadata, object_player); - - hook_associate ("current art ready", (HookFunction) update_image, object_player); + hook_associate ("playback ready", (HookFunction) update_metadata, object_player); + hook_associate ("playback stop", (HookFunction) update_metadata, object_player); + hook_associate ("tuple change", (HookFunction) update_metadata, object_player); hook_associate ("playback ready", (HookFunction) emit_seek, object_player); hook_associate ("playback seek", (HookFunction) emit_seek, object_player); + timer_add (TimerRate::Hz4, update, object_player); + g_signal_connect (object_player, "handle-next", (GCallback) next_cb, nullptr); g_signal_connect (object_player, "handle-pause", (GCallback) pause_cb, nullptr); g_signal_connect (object_player, "handle-play", (GCallback) play_cb, nullptr); diff --git a/src/neon/cert_verification.cc b/src/neon/cert_verification.cc index 8ffd952..fccb3ad 100644 --- a/src/neon/cert_verification.cc +++ b/src/neon/cert_verification.cc @@ -100,7 +100,7 @@ static bool der_read_tag_number (unsigned char * in_buffer, enum AsnType * out_type) { if (in_bufferEnd - in_buffer < 2) - return FALSE; + return false; unsigned char typeOctet = in_buffer[0]; enum AsnType typeCode = (AsnType) (typeOctet & ASNTYPE_CODE_MASK); @@ -108,12 +108,12 @@ static bool der_read_tag_number (unsigned char * in_buffer, // Variable length types are not supported. if (typeCode == ASNTYPE_VARLEN_IDENTIFIER) - return FALSE; + return false; * out_type = typeCode; * out_lengthStart = in_buffer + typeCodeLength; - return TRUE; + return true; } /** @@ -125,7 +125,7 @@ static bool der_read_content_length (unsigned char * in_buffer, unsigned char * * out_end, unsigned char * * out_nextStart) { if (in_bufferEnd - in_buffer < 1) - return FALSE; + return false; unsigned char lengthDescription = in_buffer[0]; @@ -135,10 +135,10 @@ static bool der_read_content_length (unsigned char * in_buffer, * out_end = * out_start + lengthDescription; if (in_bufferEnd < * out_end) - return FALSE; + return false; * out_nextStart = * out_end; - return TRUE; + return true; } if (lengthDescription == LENGTH_INDEFINITE_VALUE) @@ -152,21 +152,21 @@ static bool der_read_content_length (unsigned char * in_buffer, { * out_end = currentPos; * out_nextStart = * out_end + 1; - return TRUE; + return true; } } - return FALSE; + return false; } size_t lengthOctets = lengthDescription & LENGTH_LONGFORM_MASK; // We can't handle longer objects than size_t can represent. if (lengthOctets > sizeof (size_t)) - return FALSE; + return false; if (in_bufferEnd < in_buffer + 1 + lengthOctets) - return FALSE; + return false; size_t contentLength = 0; size_t i = 0; @@ -181,10 +181,10 @@ static bool der_read_content_length (unsigned char * in_buffer, * out_end = * out_start + contentLength; if (in_bufferEnd < * out_end) - return FALSE; + return false; * out_nextStart = * out_end; - return TRUE; + return true; } /** @@ -197,7 +197,7 @@ static bool der_read_content (struct DerData * data, struct DerData * content) & lengthStart, & content->type); if (! typeOk) - return FALSE; + return false; content->bufferEnd = data->bufferEnd; return der_read_content_length (lengthStart, data->bufferEnd, @@ -216,7 +216,7 @@ static bool der_read_next (struct DerData * currentContent, struct DerData * nex currentContent->bufferEnd, & lengthStart, & nextContent->type); if (! typeOk) - return FALSE; + return false; unsigned char * nextContentStart = nullptr; return der_read_content_length (lengthStart, currentContent->bufferEnd, @@ -250,26 +250,26 @@ static bool cert_get_hash (const ne_ssl_certificate * cert, uint32_t * out_hash) // Walk through certificate content until we reach subject field. // certificate - g_return_val_if_fail (der_read_content (& data, & content), FALSE); - g_return_val_if_fail (ASNTYPE_SEQUENCE == content.type, FALSE); + g_return_val_if_fail (der_read_content (& data, & content), false); + g_return_val_if_fail (ASNTYPE_SEQUENCE == content.type, false); // tbsCertificate - g_return_val_if_fail (der_read_content (& content, & content), FALSE); - g_return_val_if_fail (ASNTYPE_SEQUENCE == content.type, FALSE); + g_return_val_if_fail (der_read_content (& content, & content), false); + g_return_val_if_fail (ASNTYPE_SEQUENCE == content.type, false); // version + serialNumber - g_return_val_if_fail (der_read_content (& content, & content), FALSE); - g_return_val_if_fail (ASNTYPE_INTEGER == content.type, FALSE); + g_return_val_if_fail (der_read_content (& content, & content), false); + g_return_val_if_fail (ASNTYPE_INTEGER == content.type, false); // signature - g_return_val_if_fail (der_read_next (& content, & content), FALSE); - g_return_val_if_fail (ASNTYPE_SEQUENCE == content.type, FALSE); + g_return_val_if_fail (der_read_next (& content, & content), false); + g_return_val_if_fail (ASNTYPE_SEQUENCE == content.type, false); // issuer - g_return_val_if_fail (der_read_next (& content, & content), FALSE); - g_return_val_if_fail (ASNTYPE_SEQUENCE == content.type, FALSE); + g_return_val_if_fail (der_read_next (& content, & content), false); + g_return_val_if_fail (ASNTYPE_SEQUENCE == content.type, false); // validity - g_return_val_if_fail (der_read_next (& content, & content), FALSE); - g_return_val_if_fail (ASNTYPE_SEQUENCE == content.type, FALSE); + g_return_val_if_fail (der_read_next (& content, & content), false); + g_return_val_if_fail (ASNTYPE_SEQUENCE == content.type, false); // subject - g_return_val_if_fail (der_read_next (& content, & content), FALSE); - g_return_val_if_fail (ASNTYPE_SEQUENCE == content.type, FALSE); + g_return_val_if_fail (der_read_next (& content, & content), false); + g_return_val_if_fail (ASNTYPE_SEQUENCE == content.type, false); // Calculate MD5 sum of subject. unsigned char md5pword[16]; @@ -293,7 +293,7 @@ static bool cert_get_hash (const ne_ssl_certificate * cert, uint32_t * out_hash) * out_hash = hash; g_free (certDer); - return TRUE; + return true; } /** @@ -309,12 +309,12 @@ static bool is_signer_of_cert (const ne_ssl_certificate * signer, const ne_ssl_c while (certSigner != nullptr) { if (ne_ssl_cert_cmp (signer, certSigner) == 0) - return TRUE; + return true; certSigner = ne_ssl_cert_signedby (certSigner); } - return FALSE; + return false; } /** @@ -330,10 +330,10 @@ static bool file_is_signer_of_cert (const char * filename, const ne_ssl_certific ne_ssl_cert_free (signer); if (signOk) - return TRUE; + return true; } - return FALSE; + return false; } /** @@ -356,12 +356,12 @@ static bool validate_directory_certs (const char * directory, g_free (certPath); if (signOk) - return TRUE; + return true; certId ++; } - return FALSE; + return false; } /** diff --git a/src/neon/neon.cc b/src/neon/neon.cc index 153eba6..092809e 100644 --- a/src/neon/neon.cc +++ b/src/neon/neon.cc @@ -157,10 +157,12 @@ private: bool m_can_ranges = false; /* true if the webserver advertised accept-range: bytes */ int64_t m_icy_metaint = 0; /* Interval in which the server will send metadata announcements. 0 if no announcments */ int64_t m_icy_metaleft = 0; /* Bytes left until the next metadata block */ + int m_icy_len = 0; /* Bytes in current metadata block */ bool m_eof = false; RingBuf<char> m_rb; /* Ringbuffer for our data */ + Index<char> m_icy_buf; /* Buffer for ICY metadata */ icy_metadata m_icy_metadata; /* Current ICY metadata */ ne_session * m_session = nullptr; @@ -175,7 +177,7 @@ private: int open_request (uint64_t startbyte, String * error); FillBufferResult fill_buffer (); void reader (); - int64_t try_fread (void * ptr, int64_t size, int64_t nmemb); + int64_t try_fread (void * ptr, int64_t size, int64_t nmemb, bool & data_read); static int server_auth_callback (void * data, const char * realm, int attempt, char * username, char * password) @@ -225,7 +227,7 @@ static void add_icy (struct icy_metadata * m, const char * name, const char * va } } -static void parse_icy (struct icy_metadata * m, char * metadata, size_t len) +static void parse_icy (struct icy_metadata * m, char * metadata, int len) { enum TagReadState { @@ -239,7 +241,7 @@ static void parse_icy (struct icy_metadata * m, char * metadata, size_t len) char * p = metadata; char * tstart = metadata; - size_t pos = 1; + int pos = 1; char name[NEON_ICY_BUFSIZE]; char value[NEON_ICY_BUFSIZE]; @@ -733,7 +735,7 @@ VFSImpl * NeonTransport::fopen (const char * path, const char * mode, String & e return file; } -int64_t NeonFile::try_fread (void * ptr, int64_t size, int64_t nmemb) +int64_t NeonFile::try_fread (void * ptr, int64_t size, int64_t nmemb, bool & data_read) { if (! m_request) { @@ -852,7 +854,9 @@ int64_t NeonFile::try_fread (void * ptr, int64_t size, int64_t nmemb) /* Deliver data from the buffer */ pthread_mutex_lock (& m_reader_status.mutex); - if (! m_rb.len ()) + if (m_rb.len ()) + data_read = true; + else { /* The buffer is still empty, we can deliver no data! */ AUDERR ("<%p> Buffer still underrun, fatal.\n", this); @@ -866,31 +870,27 @@ int64_t NeonFile::try_fread (void * ptr, int64_t size, int64_t nmemb) { if (! m_icy_metaleft) { - /* The next data in the buffer is a ICY metadata announcement. - * Get the length byte */ - unsigned char icy_metalen = m_rb.head (); - m_rb.pop (); - - /* We need enough data in the buffer to - * a) Read the complete ICY metadata block - * b) deliver at least one byte to the reader */ - AUDDBG ("<%p> Expecting %d bytes of ICY metadata\n", this, (icy_metalen*16)); - - if (m_rb.len () < icy_metalen * 16 + size) + if (! m_icy_len) { - /* There is not enough data. We do not have much choice at this point, - * so we'll deliver the metadata as normal data to the reader and - * hope for the best. */ - AUDERR ("<%p> Buffer underrun when reading metadata. Expect " - "audio degradation\n", this); - m_icy_metaleft = m_icy_metaint + icy_metalen * 16; + /* The next data in the buffer is a ICY metadata announcement. + * Get the length byte */ + m_icy_len = 16 * (unsigned char) m_rb.head (); + m_rb.pop (); + + AUDDBG ("<%p> Expecting %d bytes of ICY metadata\n", this, m_icy_len); } - else + + if (m_icy_buf.len () < m_icy_len) + m_rb.move_out (m_icy_buf, -1, aud::min (m_icy_len - m_icy_buf.len (), m_rb.len ())); + + if (m_icy_buf.len () >= m_icy_len) { /* Grab the metadata from the buffer and send it to the parser */ - char icy_metadata[NEON_ICY_BUFSIZE]; - m_rb.move_out (icy_metadata, icy_metalen * 16); - parse_icy (& m_icy_metadata, icy_metadata, icy_metalen * 16); + parse_icy (& m_icy_metadata, m_icy_buf.begin (), m_icy_buf.len ()); + + /* Reset countdown to next announcement */ + m_icy_buf.clear (); + m_icy_len = 0; m_icy_metaleft = m_icy_metaint; } } @@ -927,12 +927,17 @@ int64_t NeonFile::try_fread (void * ptr, int64_t size, int64_t nmemb) * must call it repeatedly until we have read the full request. */ int64_t NeonFile::fread (void * buffer, int64_t size, int64_t count) { - size_t total = 0, part; + int64_t total = 0; AUDDBG ("<%p> fread %d x %d\n", this, (int) size, (int) count); - while (count > 0 && (part = try_fread (buffer, size, count)) > 0) + while (count > 0) { + bool data_read = false; + int64_t part = try_fread (buffer, size, count, data_read); + if (! data_read) + break; + buffer = (char *) buffer + size * part; total += part; count -= part; @@ -1057,6 +1062,8 @@ int NeonFile::fseek (int64_t offset, VFSSeekType whence) } m_rb.discard (); + m_icy_buf.clear (); + m_icy_len = 0; if (open_handle (newpos) != 0) { diff --git a/src/notify/event.cc b/src/notify/event.cc index 7134c87..f00f0d2 100644 --- a/src/notify/event.cc +++ b/src/notify/event.cc @@ -32,7 +32,7 @@ static String last_title, last_message; static GdkPixbuf * last_pixbuf = nullptr; -static void clear_cache (void) +static void clear_cache () { last_title = String (); last_message = String (); @@ -46,31 +46,31 @@ static void clear_cache (void) osd_hide (); } -static gboolean get_album_art (void) +static bool get_album_art () { if (last_pixbuf) - return FALSE; + return false; last_pixbuf = audgui_pixbuf_request_current (); if (! last_pixbuf) - return FALSE; + return false; - audgui_pixbuf_scale_within (& last_pixbuf, 96); - return TRUE; + audgui_pixbuf_scale_within (& last_pixbuf, audgui_get_dpi ()); + return true; } -static void show_stopped (void) +static void show_stopped () { osd_show (_("Stopped"), _("Audacious is not playing."), "audacious", nullptr); } -static void show_playing (void) +static void show_playing () { if (last_title && last_message) osd_show (last_title, last_message, "audio-x-generic", last_pixbuf); } -static void playback_update (void) +static void playback_update () { Tuple tuple = aud_drct_get_tuple (); String title = tuple.get_str (Tuple::Title); @@ -100,19 +100,13 @@ static void playback_update (void) show_playing (); } -static void art_ready (void) -{ - if (aud_drct_get_playing () && get_album_art ()) - show_playing (); -} - -static void playback_paused (void) +static void playback_paused () { if (aud_get_bool ("notify", "resident")) show_playing (); } -static void playback_stopped (void) +static void playback_stopped () { clear_cache (); @@ -120,7 +114,7 @@ static void playback_stopped (void) show_stopped (); } -static void force_show (void) +static void force_show () { if (aud_drct_get_playing ()) show_playing (); @@ -128,7 +122,7 @@ static void force_show (void) show_stopped (); } -void event_init (void) +void event_init () { if (aud_drct_get_ready ()) playback_update (); @@ -138,7 +132,6 @@ void event_init (void) hook_associate ("playback begin", (HookFunction) clear_cache, nullptr); hook_associate ("playback ready", (HookFunction) playback_update, nullptr); hook_associate ("tuple change", (HookFunction) playback_update, nullptr); - hook_associate ("current art ready", (HookFunction) art_ready, nullptr); hook_associate ("playback pause", (HookFunction) playback_paused, nullptr); hook_associate ("playback unpause", (HookFunction) playback_paused, nullptr); hook_associate ("playback stop", (HookFunction) playback_stopped, nullptr); @@ -146,12 +139,11 @@ void event_init (void) hook_associate ("aosd toggle", (HookFunction) force_show, nullptr); } -void event_uninit (void) +void event_uninit () { hook_dissociate ("playback begin", (HookFunction) clear_cache); hook_dissociate ("playback ready", (HookFunction) playback_update); hook_dissociate ("tuple change", (HookFunction) playback_update); - hook_dissociate ("current art ready", (HookFunction) art_ready); hook_dissociate ("playback pause", (HookFunction) playback_paused); hook_dissociate ("playback unpause", (HookFunction) playback_paused); hook_dissociate ("playback stop", (HookFunction) playback_stopped); diff --git a/src/notify/event.h b/src/notify/event.h index 5a36c66..ef63c79 100644 --- a/src/notify/event.h +++ b/src/notify/event.h @@ -17,5 +17,5 @@ * along with this program; if not, see <http://www.gnu.org/licenses/>. */ -void event_init (void); -void event_uninit (void); +void event_init (); +void event_uninit (); diff --git a/src/notify/notify.cc b/src/notify/notify.cc index ac37654..4a982d1 100644 --- a/src/notify/notify.cc +++ b/src/notify/notify.cc @@ -22,6 +22,7 @@ #include <libnotify/notify.h> +#define AUD_PLUGIN_GLIB_ONLY #include <libaudcore/plugin.h> #include <libaudcore/preferences.h> #include <libaudcore/i18n.h> @@ -80,9 +81,6 @@ const char * const NotifyPlugin::defaults[] = { bool NotifyPlugin::init () { - if (aud_get_mainloop_type () != MainloopType::GLib) - return false; - aud_config_set_defaults ("notify", defaults); if (! notify_init ("Audacious")) diff --git a/src/notify/osd.cc b/src/notify/osd.cc index d2ebfe2..7af7255 100644 --- a/src/notify/osd.cc +++ b/src/notify/osd.cc @@ -27,19 +27,19 @@ #include <libaudcore/interface.h> #include <libaudcore/runtime.h> -static void show_cb (void) +static void show_cb () { - aud_ui_show (TRUE); + aud_ui_show (true); } static void osd_setup (NotifyNotification *notification) { - gboolean resident = aud_get_bool ("notify", "resident"); + bool resident = aud_get_bool ("notify", "resident"); notify_notification_set_hint (notification, "desktop-entry", g_variant_new_string ("audacious")); - notify_notification_set_hint (notification, "action-icons", g_variant_new_boolean (TRUE)); + notify_notification_set_hint (notification, "action-icons", g_variant_new_boolean (true)); notify_notification_set_hint (notification, "resident", g_variant_new_boolean (resident)); notify_notification_set_hint (notification, "transient", g_variant_new_boolean (! resident)); @@ -58,8 +58,8 @@ void osd_setup_buttons (NotifyNotification *notification) notify_notification_add_action (notification, "default", _("Show"), NOTIFY_ACTION_CALLBACK (show_cb), nullptr, nullptr); - gboolean playing = aud_drct_get_playing (); - gboolean paused = aud_drct_get_paused (); + bool playing = aud_drct_get_playing (); + bool paused = aud_drct_get_paused (); if (playing && ! paused) notify_notification_add_action (notification, "media-playback-pause", @@ -100,7 +100,7 @@ void osd_show (const char * title, const char * _message, const char * icon, g_free (message); } -void osd_hide (void) +void osd_hide () { if (! notification) return; diff --git a/src/notify/osd.h b/src/notify/osd.h index 604ebfe..0a2c4c2 100644 --- a/src/notify/osd.h +++ b/src/notify/osd.h @@ -20,4 +20,4 @@ #include <gdk-pixbuf/gdk-pixbuf.h> void osd_show (const char * title, const char * message, const char * icon, GdkPixbuf * pixbuf); -void osd_hide (void); +void osd_hide (); diff --git a/src/oss4/oss.cc b/src/oss4/oss.cc index 923449d..6c1a8dc 100644 --- a/src/oss4/oss.cc +++ b/src/oss4/oss.cc @@ -206,11 +206,14 @@ bool OSSPlugin::open_audio(int aud_format, int rate, int channels) int format; audio_buf_info buf_info; + bool poll_was_setup = false; CHECK_NOISY(m_fd = open_device); - if (!poll_setup(m_fd)) - goto CLOSE; + if (poll_setup(m_fd)) + poll_was_setup = true; + else + goto FAILED; format = oss_convert_aud_format(aud_format); @@ -228,7 +231,6 @@ bool OSSPlugin::open_audio(int aud_format, int rate, int channels) buf_info.fragsize, buf_info.bytes); - m_paused = false; m_ioctl_vol = true; if (aud_get_bool("oss4", "save_volume")) @@ -237,9 +239,10 @@ bool OSSPlugin::open_audio(int aud_format, int rate, int channels) return true; FAILED: - poll_cleanup(); -CLOSE: - close_device(m_fd); + if (poll_was_setup) + poll_cleanup(); + if (m_fd >= 0) + close_device(m_fd); return false; } @@ -253,9 +256,6 @@ void OSSPlugin::close_audio() int OSSPlugin::write_audio(const void *data, int length) { - if (m_paused) - return 0; - int written = write(m_fd, data, length); if (written < 0) @@ -312,8 +312,8 @@ void OSSPlugin::pause(bool pause) CHECK(ioctl, m_fd, SNDCTL_DSP_SKIP, nullptr); FAILED: + return; #endif - m_paused = pause; } StereoVolume OSSPlugin::get_volume() diff --git a/src/oss4/oss.h b/src/oss4/oss.h index 4de8110..aff7bb6 100644 --- a/src/oss4/oss.h +++ b/src/oss4/oss.h @@ -139,7 +139,6 @@ private: int m_channels = 0; int m_bytes_per_sample = 0; - bool m_paused = false; bool m_ioctl_vol = false; }; diff --git a/src/oss4/plugin.cc b/src/oss4/plugin.cc index dd02694..c710b43 100644 --- a/src/oss4/plugin.cc +++ b/src/oss4/plugin.cc @@ -54,7 +54,8 @@ static void combo_init() #endif FAILED: - close(mixerfd); + if (mixerfd >= 0) + close(mixerfd); } ArrayRef<ComboItem> combo_fill() diff --git a/src/oss4/utils.cc b/src/oss4/utils.cc index 22fd78a..35f6e67 100644 --- a/src/oss4/utils.cc +++ b/src/oss4/utils.cc @@ -199,6 +199,7 @@ bool oss_hardware_present() return true; FAILED: - close(mixerfd); + if (mixerfd >= 0) + close(mixerfd); return false; } diff --git a/src/playlist-manager-qt/Makefile b/src/playlist-manager-qt/Makefile new file mode 100644 index 0000000..1b3f0a5 --- /dev/null +++ b/src/playlist-manager-qt/Makefile @@ -0,0 +1,13 @@ +PLUGIN = playlist-manager-qt${PLUGIN_SUFFIX} + +SRCS = playlist-manager-qt.cc + +include ../../buildsys.mk +include ../../extra.mk + +plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR} + +LD = ${CXX} +CPPFLAGS += -I../.. ${QT_CFLAGS} +CFLAGS += ${PLUGIN_CFLAGS} +LIBS += ${QT_LIBS} -laudqt diff --git a/src/playlist-manager-qt/playlist-manager-qt.cc b/src/playlist-manager-qt/playlist-manager-qt.cc new file mode 100644 index 0000000..17907e6 --- /dev/null +++ b/src/playlist-manager-qt/playlist-manager-qt.cc @@ -0,0 +1,336 @@ +/* + * playlist-manager-qt.cc + * Copyright 2015 John Lindgren + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions, and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions, and the following disclaimer in the documentation + * provided with the distribution. + * + * This software is provided "as is" and without any warranty, express or + * implied. In no event shall the authors be liable for any damages arising from + * the use of this software. + */ + +#include <QAbstractListModel> +#include <QFont> +#include <QGuiApplication> +#include <QHeaderView> +#include <QIcon> +#include <QMouseEvent> +#include <QToolButton> +#include <QTreeView> +#include <QVBoxLayout> + +#define AUD_PLUGIN_QT_ONLY +#include <libaudcore/hook.h> +#include <libaudcore/i18n.h> +#include <libaudcore/playlist.h> +#include <libaudcore/plugin.h> +#include <libaudqt/libaudqt.h> + +class PlaylistManagerQt : public GeneralPlugin +{ +public: + static constexpr PluginInfo info = { + N_("Playlist Manager"), + PACKAGE + }; + + constexpr PlaylistManagerQt () : GeneralPlugin (info, false) {} + + void * get_qt_widget (); +}; + +EXPORT PlaylistManagerQt aud_plugin_instance; + +class PlaylistsModel : public QAbstractListModel +{ +public: + enum { + ColumnTitle, + ColumnEntries, + NColumns + }; + + PlaylistsModel () : + m_rows (aud_playlist_count ()), + m_playing (aud_playlist_get_playing ()), + m_bold (QGuiApplication::font ()) + { + m_bold.setBold (true); + } + + void update (Playlist::UpdateLevel level); + +protected: + int rowCount (const QModelIndex & parent) const { return m_rows; } + int columnCount (const QModelIndex & parent) const { return NColumns; } + + Qt::DropActions supportedDropActions () const { return Qt::MoveAction; } + + Qt::ItemFlags flags (const QModelIndex & index) const + { + if (index.isValid ()) + return Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled; + else + return Qt::ItemIsSelectable | Qt::ItemIsDropEnabled | Qt::ItemIsEnabled; + } + + QVariant data (const QModelIndex & index, int role) const; + QVariant headerData (int section, Qt::Orientation orientation, int role) const; + +private: + void update_rows (int row, int count); + void update_playing (); + + const HookReceiver<PlaylistsModel> + activate_hook {"playlist set playing", this, & PlaylistsModel::update_playing}; + + int m_rows, m_playing; + QFont m_bold; +}; + +class PlaylistsView : public QTreeView +{ +public: + PlaylistsView (); + +protected: + void currentChanged (const QModelIndex & current, const QModelIndex & previous); + void mouseDoubleClickEvent (QMouseEvent * event); + void dropEvent (QDropEvent * event); + +private: + PlaylistsModel m_model; + + void update (Playlist::UpdateLevel level); + void update_sel (); + + const HookReceiver<PlaylistsView, Playlist::UpdateLevel> + update_hook {"playlist update", this, & PlaylistsView::update}; + const HookReceiver<PlaylistsView> + activate_hook {"playlist activate", this, & PlaylistsView::update_sel}; + + int m_in_update = 0; +}; + +QVariant PlaylistsModel::data (const QModelIndex & index, int role) const +{ + switch (role) + { + case Qt::DisplayRole: + switch (index.column ()) + { + case ColumnTitle: + return QString (aud_playlist_get_title (index.row ())); + case ColumnEntries: + return aud_playlist_entry_count (index.row ()); + } + break; + + case Qt::FontRole: + if (index.row () == m_playing) + return m_bold; + break; + + case Qt::TextAlignmentRole: + if (index.column () == ColumnEntries) + return Qt::AlignRight; + break; + } + + return QVariant (); +} + +QVariant PlaylistsModel::headerData (int section, Qt::Orientation orientation, int role) const +{ + if (orientation == Qt::Horizontal && role == Qt::DisplayRole) + { + switch (section) + { + case ColumnTitle: + return QString (_("Title")); + case ColumnEntries: + return QString (_("Entries")); + } + } + + return QVariant (); +} + +void PlaylistsModel::update_rows (int row, int count) +{ + if (count < 1) + return; + + auto topLeft = createIndex (row, 0); + auto bottomRight = createIndex (row + count - 1, NColumns - 1); + emit dataChanged (topLeft, bottomRight); +} + +void PlaylistsModel::update_playing () +{ + if (aud_playlist_update_pending ()) + return; + + int playing = aud_playlist_get_playing (); + + if (playing != m_playing) + { + if (m_playing >= 0) + update_rows (m_playing, 1); + if (playing >= 0) + update_rows (playing, 1); + + m_playing = playing; + } +} + +void PlaylistsModel::update (const Playlist::UpdateLevel level) +{ + int rows = aud_playlist_count (); + + if (level == Playlist::Structure) + { + if (rows < m_rows) + { + beginRemoveRows (QModelIndex (), rows, m_rows - 1); + m_rows = rows; + endRemoveRows (); + } + else if (rows > m_rows) + { + beginInsertRows (QModelIndex (), m_rows, rows - 1); + m_rows = rows; + endInsertRows (); + } + } + + if (level >= Playlist::Metadata) + { + update_rows (0, m_rows); + m_playing = aud_playlist_get_playing (); + } + else + update_playing (); +} + +PlaylistsView::PlaylistsView () +{ + m_in_update ++; + setModel (& m_model); + update_sel (); + m_in_update --; + + auto hdr = header (); + hdr->setStretchLastSection (false); + hdr->setSectionResizeMode (PlaylistsModel::ColumnTitle, QHeaderView::Stretch); + hdr->setSectionResizeMode (PlaylistsModel::ColumnEntries, QHeaderView::Interactive); + hdr->resizeSection (PlaylistsModel::ColumnEntries, 64); + + setDragDropMode (InternalMove); + setIndentation (0); +} + +void PlaylistsView::currentChanged (const QModelIndex & current, const QModelIndex & previous) +{ + QTreeView::currentChanged (current, previous); + if (! m_in_update) + aud_playlist_set_active (current.row ()); +} + +void PlaylistsView::mouseDoubleClickEvent (QMouseEvent * event) +{ + if (event->button () == Qt::LeftButton) + aud_playlist_play (currentIndex ().row ()); +} + +void PlaylistsView::dropEvent (QDropEvent * event) +{ + if (event->source () != this || event->proposedAction () != Qt::MoveAction) + return; + + int from = currentIndex ().row (); + if (from < 0) + return; + + int to; + switch (dropIndicatorPosition ()) + { + case AboveItem: to = indexAt (event->pos ()).row (); break; + case BelowItem: to = indexAt (event->pos ()).row () + 1; break; + case OnViewport: to = aud_playlist_count (); break; + default: return; + } + + aud_playlist_reorder (from, (to > from) ? to - 1 : to, 1); + event->acceptProposedAction (); +} + +void PlaylistsView::update (Playlist::UpdateLevel level) +{ + m_in_update ++; + m_model.update (level); + update_sel (); + m_in_update --; +} + +void PlaylistsView::update_sel () +{ + if (aud_playlist_update_pending ()) + return; + + m_in_update ++; + auto sel = selectionModel (); + auto current = m_model.index (aud_playlist_get_active (), 0); + sel->setCurrentIndex (current, sel->ClearAndSelect | sel->Rows); + m_in_update --; +} + +static QToolButton * new_tool_button (const char * text, const char * icon) +{ + auto button = new QToolButton; + button->setIcon (QIcon::fromTheme (icon)); + button->setText (audqt::translate_str (text)); + button->setToolButtonStyle (Qt::ToolButtonTextBesideIcon); + return button; +} + +void * PlaylistManagerQt::get_qt_widget () +{ + auto widget = new QWidget; + auto vbox = new QVBoxLayout (widget); + vbox->setContentsMargins (0, 0, 0, 0); + + auto view = new PlaylistsView; + vbox->addWidget (view, 1); + + auto hbox = new QHBoxLayout; + vbox->addLayout (hbox); + + auto new_button = new_tool_button (N_("_New"), "document-new"); + QObject::connect (new_button, & QToolButton::clicked, aud_playlist_new); + + auto rename_button = new_tool_button (N_("Ren_ame"), "insert-text"); + QObject::connect (rename_button, & QToolButton::clicked, [] () { + audqt::playlist_show_rename (aud_playlist_get_active ()); + }); + + auto remove_button = new_tool_button (N_("_Remove"), "edit-delete"); + QObject::connect (remove_button, & QToolButton::clicked, [] () { + audqt::playlist_confirm_delete (aud_playlist_get_active ()); + }); + + hbox->addWidget (new_button); + hbox->addWidget (rename_button); + hbox->addStretch (1); + hbox->addWidget (remove_button); + + return widget; +} diff --git a/src/playlist-manager/playlist-manager.cc b/src/playlist-manager/playlist-manager.cc index a006aac..9c46a25 100644 --- a/src/playlist-manager/playlist-manager.cc +++ b/src/playlist-manager/playlist-manager.cc @@ -17,6 +17,7 @@ * the use of this software. */ +#define AUD_PLUGIN_GLIB_ONLY #include <libaudcore/audstrings.h> #include <libaudcore/hook.h> #include <libaudcore/i18n.h> @@ -55,12 +56,6 @@ static void rename_cb (void * unused) audgui_show_playlist_rename (aud_playlist_get_active ()); } -static void new_cb (void * unused) -{ - aud_playlist_insert (aud_playlist_get_active () + 1); - aud_playlist_set_active (aud_playlist_get_active () + 1); -} - static void delete_cb (void * unused) { audgui_confirm_playlist_delete (aud_playlist_get_active ()); @@ -241,7 +236,8 @@ void * PlaylistManager::get_gtk_widget () /* ButtonBox */ GtkWidget * playman_button_hbox = gtk_hbox_new (false, 6); - GtkWidget * new_button = audgui_button_new (_("_New"), "document-new", new_cb, nullptr); + GtkWidget * new_button = audgui_button_new (_("_New"), "document-new", + (AudguiCallback) aud_playlist_new, nullptr); GtkWidget * delete_button = audgui_button_new (_("_Remove"), "edit-delete", delete_cb, nullptr); GtkWidget * rename_button = audgui_button_new (_("Ren_ame"), "insert-text", rename_cb, nullptr); diff --git a/src/psf/eng_protos.h b/src/psf/eng_protos.h index d3488eb..3845aee 100644 --- a/src/psf/eng_protos.h +++ b/src/psf/eng_protos.h @@ -1,4 +1,5 @@ -#include <libaudcore/plugin.h> +#include <stdint.h> +#include <libaudcore/tuple.h> int32_t psf2_start(uint8_t *, uint32_t length); int32_t psf2_execute(void (*update)(const void *, int)); diff --git a/src/qtui/Makefile b/src/qtui/Makefile index 0581231..5808c32 100644 --- a/src/qtui/Makefile +++ b/src/qtui/Makefile @@ -11,7 +11,8 @@ SRCS = qtui.cc \ info_bar.cc \ status_bar.cc \ tool_bar.cc \ - time_slider.cc + time_slider.cc \ + settings.cc include ../../buildsys.mk include ../../extra.mk diff --git a/src/qtui/dialog_windows.cc b/src/qtui/dialog_windows.cc index b5575e5..1a0b720 100644 --- a/src/qtui/dialog_windows.cc +++ b/src/qtui/dialog_windows.cc @@ -19,8 +19,8 @@ #include "dialog_windows.h" -#include <QMessageBox> #include <libaudcore/i18n.h> +#include <libaudqt/libaudqt.h> void DialogWindows::create_progress () { @@ -28,36 +28,27 @@ void DialogWindows::create_progress () { m_progress = new QMessageBox (m_parent); m_progress->setIcon (QMessageBox::Information); - m_progress->setText (_("Working ...")); - m_progress->setStandardButtons (QMessageBox::NoButton); + m_progress->setWindowTitle (_("Working ...")); m_progress->setWindowModality (Qt::WindowModal); } } void DialogWindows::show_error (const char * message) { - if (! m_error) - { - m_error = new QMessageBox (m_parent); - m_error->setIcon (QMessageBox::Warning); - m_error->setWindowModality (Qt::WindowModal); - } - - m_error->setText (message); - m_error->show (); + audqt::simple_message (_("Error"), message, QMessageBox::Critical); } void DialogWindows::show_progress (const char * message) { create_progress (); - m_progress->setInformativeText (message); + m_progress->setText (message); m_progress->show (); } void DialogWindows::show_progress_2 (const char * message) { create_progress (); - m_progress->setText (message); + m_progress->setInformativeText (message); m_progress->show (); } diff --git a/src/qtui/dialog_windows.h b/src/qtui/dialog_windows.h index d226bc8..8b5468d 100644 --- a/src/qtui/dialog_windows.h +++ b/src/qtui/dialog_windows.h @@ -34,7 +34,6 @@ public: private: QWidget * m_parent; QMessageBox * m_progress = nullptr; - QMessageBox * m_error = nullptr; void create_progress (); void show_error (const char * message); @@ -50,4 +49,4 @@ private: hide_hook {"ui hide progress", this, & DialogWindows::hide_progress}; }; -#endif // DIALOG_WINDOWS_H +#endif diff --git a/src/qtui/filter_input.cc b/src/qtui/filter_input.cc index e1977b5..98c6423 100644 --- a/src/qtui/filter_input.cc +++ b/src/qtui/filter_input.cc @@ -46,7 +46,7 @@ FilterInput::FilterInput (QWidget * parent) : QLineEdit (parent) void FilterInput::keyPressEvent (QKeyEvent * e) { - if (e->key () == Qt::Key_Enter or e->key () == Qt::Key_Return) + if (e->key () == Qt::Key_Enter || e->key () == Qt::Key_Return) { e->ignore (); focusNextChild (); diff --git a/src/qtui/filter_input.h b/src/qtui/filter_input.h index 41559a2..52d8689 100644 --- a/src/qtui/filter_input.h +++ b/src/qtui/filter_input.h @@ -17,8 +17,8 @@ * the use of this software. */ -#ifndef FILTER_INPUT_WIDGET_H -#define FILTER_INPUT_WIDGET_H +#ifndef FILTER_INPUT_H +#define FILTER_INPUT_H #include <QLineEdit> diff --git a/src/qtui/info_bar.cc b/src/qtui/info_bar.cc index b62517f..f80e5d7 100644 --- a/src/qtui/info_bar.cc +++ b/src/qtui/info_bar.cc @@ -21,60 +21,94 @@ #include "info_bar.h" -#include <libaudcore/hook.h> -#include <libaudcore/index.h> -#include <libaudcore/objects.h> -#include <libaudcore/runtime.h> -#include <libaudcore/interface.h> -#include <libaudcore/tuple.h> #include <libaudcore/drct.h> +#include <libaudcore/interface.h> #include <libaudqt/libaudqt.h> -#include <QGraphicsItem> -#include <QGraphicsPixmapItem> -#include <QFont> +#include <QPainter> -VisItem::VisItem (QGraphicsItem * parent) : - QGraphicsItem (parent), - Visualizer (Freq) -{ - aud_visualizer_add (this); -} +static constexpr int Spacing = 8; +static constexpr int IconSize = 64; +static constexpr int Height = IconSize + 2 * Spacing; + +static constexpr int VisBands = 12; +static constexpr int VisWidth = 8 * VisBands + Spacing - 2; +static constexpr int VisCenter = IconSize * 5 / 8 + Spacing; +static constexpr int VisDelay = 2; +static constexpr int VisFalloff = 2; -VisItem::~VisItem () +class InfoVis : public QWidget, Visualizer { - aud_visualizer_remove (this); -} +public: + InfoVis (QWidget * parent = nullptr); + ~InfoVis (); + + void render_freq (const float * freq); + void clear (); + + void paintEvent (QPaintEvent *); + + const QGradient & gradient () const + { return m_gradient; } -QRectF VisItem::boundingRect () const +private: + QLinearGradient m_gradient; + QColor m_colors[VisBands], m_shadow[VisBands]; + + char m_bars[VisBands] {}; + char m_delay[VisBands] {}; +}; + +static void get_color (int i, QColor & color, QColor & shadow) { - return QRectF (0.0, 0.0, InfoBar::VisWidth, InfoBar::Height); + color = QWidget ().palette ().color (QPalette::Highlight); + + qreal h, s, v; + color.getHsvF (& h, & s, & v); + + if (s < 0.1) /* monochrome theme? use blue instead */ + h = 0.67; + + s = 1 - 0.9 * i / (VisBands - 1); + v = 0.75 + 0.25 * i / (VisBands - 1); + + color.setHsvF (h, s, v); + shadow = QColor (color.redF () * 77, color.greenF () * 77, color.blueF () * 77); } -void VisItem::paint (QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget) +InfoVis::InfoVis (QWidget * parent) : + QWidget (parent), + Visualizer (Freq), + m_gradient (0, 0, 0, Height) { - QColor c = Qt::blue; + m_gradient.setStops ({ + {0, QColor (64, 64, 64)}, + {0.499, QColor (38, 38, 38)}, + {0.5, QColor (26, 26, 26)}, + {1, QColor (0, 0, 0)} + }); - painter->fillRect (boundingRect (), QColor (0, 0, 0, 0)); - painter->setPen (QPen (c, 1, Qt::SolidLine, Qt::SquareCap, Qt::BevelJoin)); + for (int i = 0; i < VisBands; i ++) + get_color (i, m_colors[i], m_shadow[i]); - for (int i = 0; i < InfoBar::VisBands; i++) - { - int x = InfoBar::Spacing + 8 * i; - int q = InfoBar::IconSize - m_bars[i]; - int t = -(InfoBar::IconSize - q); + setAttribute (Qt::WA_OpaquePaintEvent); + resize (VisWidth, Height); - painter->fillRect (x, InfoBar::IconSize, 6, t, c); - } + aud_visualizer_add (this); } -void VisItem::render_freq (const float * freq) +InfoVis::~InfoVis () +{ + aud_visualizer_remove (this); +} + +void InfoVis::render_freq (const float * freq) { /* xscale[i] = pow (256, i / VIS_BANDS) - 0.5; */ - const float xscale[InfoBar::VisBands + 1] = {0.5, 1.09, 2.02, 3.5, 5.85, 9.58, + const float xscale[VisBands + 1] = {0.5, 1.09, 2.02, 3.5, 5.85, 9.58, 15.5, 24.9, 39.82, 63.5, 101.09, 160.77, 255.5}; - for (int i = 0; i < InfoBar::VisBands; i ++) + for (int i = 0; i < VisBands; i ++) { int a = ceilf (xscale[i]); int b = floorf (xscale[i + 1]); @@ -96,7 +130,7 @@ void VisItem::render_freq (const float * freq) int x = 40 + 20 * log10f (n); x = aud::clamp (x, 0, 40); - m_bars[i] -= aud::max (0, InfoBar::VisFalloff - m_delay[i]); + m_bars[i] -= aud::max (0, VisFalloff - m_delay[i]); if (m_delay[i]) m_delay[i] --; @@ -104,14 +138,14 @@ void VisItem::render_freq (const float * freq) if (x > m_bars[i]) { m_bars[i] = x; - m_delay[i] = InfoBar::VisDelay; + m_delay[i] = VisDelay; } } - update (); + repaint (); } -void VisItem::clear () +void InfoVis::clear () { memset (m_bars, 0, sizeof m_bars); memset (m_delay, 0, sizeof m_delay); @@ -119,93 +153,92 @@ void VisItem::clear () update (); } -void AlbumArtItem::update_cb () +void InfoVis::paintEvent (QPaintEvent *) { - setPixmap (audqt::art_request_current (InfoBar::IconSize, InfoBar::IconSize)); + QPainter p (this); + p.fillRect (0, 0, VisWidth, Height, m_gradient); + + for (int i = 0; i < VisBands; i ++) + { + int x = 8 * i; + int v = m_bars[i]; + int m = aud::min (VisCenter + v, Height); + + p.fillRect (x, VisCenter - v, 6, v, m_colors[i]); + p.fillRect (x, VisCenter, 6, m - VisCenter, m_shadow[i]); + } } -InfoBar::InfoBar (QWidget * parent) : QGraphicsView (parent), - m_scene (new QGraphicsScene (this)), - m_art (new AlbumArtItem), - m_title_text (new QGraphicsTextItem), - m_album_text (new QGraphicsTextItem), - m_artist_text (new QGraphicsTextItem) -#ifdef XXX_NOTYET - m_vis (new VisItem) -#endif +InfoBar::InfoBar (QWidget * parent) : + QWidget (parent), + m_vis (new InfoVis (this)) { - setAlignment (Qt::AlignLeft | Qt::AlignTop); - setScene (m_scene); - setFixedHeight (InfoBar::Height); - setCacheMode (QGraphicsView::CacheBackground); - - m_scene->addItem (m_art); - m_scene->addItem (m_title_text); - m_scene->addItem (m_album_text); - m_scene->addItem (m_artist_text); -#ifdef XXX_NOTYET - m_scene->addItem (m_vis); -#endif - - m_title_text->setDefaultTextColor (QColor (255, 255, 255)); - m_artist_text->setDefaultTextColor (QColor (255, 255, 255)); - m_album_text->setDefaultTextColor (QColor (179, 179, 179)); - - QFont f = m_title_text->font (); - f.setPointSize (18); - m_title_text->setFont (f); - - f = m_artist_text->font (); - f.setPointSize (9); - m_artist_text->setFont (f); - - f = m_album_text->font (); - f.setPointSize (9); - m_album_text->setFont (f); + setFixedHeight (Height); + + m_title.setTextFormat (Qt::PlainText); + m_artist.setTextFormat (Qt::PlainText); + m_album.setTextFormat (Qt::PlainText); + + update_cb (); } -QSize InfoBar::minimumSizeHint () const +void InfoBar::resizeEvent (QResizeEvent *) { - return QSize (InfoBar::IconSize + (2 * InfoBar::Spacing), InfoBar::Height); + m_title.setText (QString ()); + m_vis->move (width () - VisWidth, 0); } -void InfoBar::resizeEvent (QResizeEvent * event) +void InfoBar::paintEvent (QPaintEvent *) { - QGraphicsView::resizeEvent (event); + QPainter p (this); - QRect rect = contentsRect (); - setSceneRect (rect); + p.fillRect (0, 0, width () - VisWidth, Height, m_vis->gradient ()); - QLinearGradient gradient (0, 0, 0, rect.height ()); - gradient.setStops ({ - {0, QColor (64, 64, 64)}, - {0.499, QColor (38, 38, 38)}, - {0.5, QColor (26, 26, 26)}, - {1, QColor (0, 0, 0)} - }); - m_scene->setBackgroundBrush (gradient); + if (! m_art.isNull ()) + { + int r = m_art.devicePixelRatio (); + int left = Spacing + (IconSize - m_art.width () / r) / 2; + int top = Spacing + (IconSize - m_art.height () / r) / 2; + p.drawPixmap (left, top, m_art); + } + + QFont font = p.font (); + font.setPointSize (18); + p.setFont (font); + + if (m_title.text ().isNull () && ! m_original_title.isNull ()) + { + QFontMetrics metrics = p.fontMetrics (); + m_title = metrics.elidedText (m_original_title, Qt::ElideRight, + width () - VisWidth - Height - Spacing); + } - m_art->setPos (InfoBar::Spacing, InfoBar::Spacing); + p.setPen (QColor (255, 255, 255)); + p.drawStaticText (Height, Spacing, m_title); - qreal x = InfoBar::IconSize + (InfoBar::Spacing * 1.5); - qreal y = InfoBar::Spacing / 2; - m_title_text->setPos (x, y); - m_artist_text->setPos (x, y + (InfoBar::IconSize / 2)); - m_album_text->setPos (x, y + ((InfoBar::IconSize * 3) / 4)); + font.setPointSize (9); + p.setFont (font); -#ifdef XXX_NOTYET - m_vis->setPos ((rect.width () - InfoBar::VisWidth) - (InfoBar::Spacing * 2), 0); -#endif + p.drawStaticText (Height, Spacing + IconSize / 2, m_artist); + + p.setPen (QColor (179, 179, 179)); + p.drawStaticText (Height, Spacing + IconSize * 3 / 4, m_album); } void InfoBar::update_metadata_cb () { Tuple tuple = aud_drct_get_tuple (); - String title = tuple.get_str (Tuple::Title); - String artist = tuple.get_str (Tuple::Artist); - String album = tuple.get_str (Tuple::Album); - m_title_text->setPlainText (QString ((const char *) title)); - m_artist_text->setPlainText (QString ((const char *) artist)); - m_album_text->setPlainText (QString ((const char *) album)); + m_title.setText (QString ()); + m_original_title = tuple.get_str (Tuple::Title); + m_artist.setText ((const char *) tuple.get_str (Tuple::Artist)); + m_album.setText ((const char *) tuple.get_str (Tuple::Album)); + + update (); +} + +void InfoBar::update_cb () +{ + m_art = audqt::art_request_current (IconSize, IconSize); + update_metadata_cb (); } diff --git a/src/qtui/info_bar.h b/src/qtui/info_bar.h index f8cabbc..75b5a30 100644 --- a/src/qtui/info_bar.h +++ b/src/qtui/info_bar.h @@ -17,80 +17,38 @@ * the use of this software. */ -#include <QWidget> -#include <QPainter> -#include <QGraphicsView> -#include <QGraphicsPixmapItem> -#include <QGraphicsTextItem> - -#include <libaudcore/hook.h> -#include <libaudcore/runtime.h> -#include <libaudcore/visualizer.h> - #ifndef INFO_BAR_H #define INFO_BAR_H -class VisItem : public QGraphicsItem, public Visualizer { -public: - VisItem (QGraphicsItem * parent = nullptr); - ~VisItem (); - - QRectF boundingRect () const; - void paint (QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr); - -private: - void render_freq (const float * freq); - void clear (); - - char m_bars[12]; - char m_delay[12]; -}; +#include <QStaticText> +#include <QWidget> -class AlbumArtItem : public QGraphicsPixmapItem { -private: - void update_cb (); +#include <libaudcore/hook.h> +#include <libaudcore/visualizer.h> - const HookReceiver<AlbumArtItem> - hook1 {"playback ready", this, & AlbumArtItem::update_cb}, - hook2 {"playback stop", this, & AlbumArtItem::update_cb}, - hook3 {"current art ready", this, & AlbumArtItem::update_cb}; -}; +class InfoVis; -class InfoBar : public QGraphicsView { +class InfoBar : public QWidget +{ public: InfoBar (QWidget * parent = nullptr); - static constexpr int Spacing = 8; - static constexpr int IconSize = 64; - static constexpr int Height = IconSize + (2 * Spacing); - - static constexpr int VisBands = 12; - static constexpr int VisWidth = (8 * VisBands) + Spacing; - static constexpr int VisCenter = (IconSize * 5 / 8 + Spacing); - static constexpr int VisDelay = 2; - static constexpr int VisFalloff = 2; - - QSize minimumSizeHint () const; void resizeEvent (QResizeEvent *); + void paintEvent (QPaintEvent *); private: - QGraphicsScene * m_scene; - AlbumArtItem * m_art; - - QGraphicsTextItem * m_title_text; - QGraphicsTextItem * m_album_text; - QGraphicsTextItem * m_artist_text; - -#ifdef XXX_NOTYET - VisItem * m_vis; -#endif - void update_metadata_cb (); + void update_cb (); const HookReceiver<InfoBar> hook1 {"tuple change", this, & InfoBar::update_metadata_cb}, - hook2 {"playback ready", this, & InfoBar::update_metadata_cb}, - hook3 {"playback stop", this, & InfoBar::update_metadata_cb}; + hook2 {"playback ready", this, & InfoBar::update_cb}, + hook3 {"playback stop", this, & InfoBar::update_cb}; + + QPixmap m_art; + QString m_original_title; + QStaticText m_title, m_artist, m_album; + InfoVis * m_vis; }; #endif diff --git a/src/qtui/main_window.cc b/src/qtui/main_window.cc index f0ccfc7..6f0b56d 100644 --- a/src/qtui/main_window.cc +++ b/src/qtui/main_window.cc @@ -22,7 +22,6 @@ #include <libaudcore/drct.h> #include <libaudcore/i18n.h> #include <libaudcore/runtime.h> -#include <libaudcore/plugin.h> #include <libaudcore/plugins.h> #include <libaudqt/libaudqt.h> @@ -40,6 +39,30 @@ #include <QAction> #include <QSettings> +class PluginWidget : public QDockWidget +{ +public: + PluginWidget (PluginHandle * plugin) : + m_plugin (plugin) + { + setObjectName (aud_plugin_get_basename (plugin)); + setWindowTitle (aud_plugin_get_name (plugin)); + setContextMenuPolicy (Qt::PreventContextMenu); + } + + PluginHandle * plugin () const { return m_plugin; } + +protected: + void closeEvent (QCloseEvent * event) + { + aud_plugin_enable (m_plugin, false); + event->ignore (); + } + +private: + PluginHandle * m_plugin; +}; + MainWindow::MainWindow () : m_dialogs (this), filterInput (new FilterInput (this)), @@ -54,8 +77,6 @@ MainWindow::MainWindow () : QStringList paths = QIcon::themeSearchPaths (); paths.prepend (aud_get_path (AudPath::DataDir)); QIcon::setThemeSearchPaths (paths); -#else - QApplication::setWindowIcon (QIcon::fromTheme ("audacious")); #endif auto slider = new TimeSlider (this); @@ -97,48 +118,52 @@ MainWindow::MainWindow () : centralLayout->setContentsMargins (0, 0, 0, 0); centralLayout->setSpacing (4); - connect (filterInput, &QLineEdit::textChanged, playlistTabs, &PlaylistTabs::filterTrigger); + connect (filterInput, & QLineEdit::textChanged, playlistTabs, & PlaylistTabs::filterTrigger); setupActions (); add_dock_plugins (); - buffering_timer.setSingleShot (true); - connect (& buffering_timer, & QTimer::timeout, this, & MainWindow::show_buffering); - if (aud_drct_get_playing ()) { playback_begin_cb (); if (aud_drct_get_ready ()) - playback_ready_cb (); + title_change_cb (); } else playback_stop_cb (); - title_change_cb (); - readSettings (); } MainWindow::~MainWindow () { + QSettings settings ("audacious", "QtUi"); + settings.setValue ("geometry", saveGeometry ()); + settings.setValue ("windowState", saveState ()); + remove_dock_plugins (); } void MainWindow::closeEvent (QCloseEvent * e) { - QSettings settings ("audacious", "QtUi"); - settings.setValue ("geometry", saveGeometry()); - settings.setValue ("windowState", saveState()); + bool handled = false; + + hook_call ("window close", & handled); + + if (! handled) + aud_quit (); - aud_quit (); e->ignore (); } void MainWindow::readSettings () { QSettings settings ("audacious", "QtUi"); - restoreGeometry (settings.value ("geometry").toByteArray()); - restoreState (settings.value ("windowState").toByteArray()); + + if (! restoreGeometry (settings.value ("geometry").toByteArray ())) + resize (768, 480); + + restoreState (settings.value ("windowState").toByteArray ()); } void MainWindow::keyPressEvent (QKeyEvent * e) @@ -180,17 +205,14 @@ void MainWindow::update_play_pause () } } -void MainWindow::show_buffering () -{ - if (aud_drct_get_playing () && ! aud_drct_get_ready ()) - setWindowTitle (_("Buffering ...")); -} - void MainWindow::title_change_cb () { auto title = aud_drct_get_title (); if (title) + { setWindowTitle (QString (title) + QString (" - Audacious")); + buffering_timer.stop (); + } } void MainWindow::playback_begin_cb () @@ -211,12 +233,9 @@ void MainWindow::playback_begin_cb () playing_id = aud_playlist_get_unique_id (list); - buffering_timer.start (250); -} - -void MainWindow::playback_ready_cb () -{ - title_change_cb (); + buffering_timer.queue (250, [] (void * me) { + ((MainWindow *) me)->setWindowTitle (_("Buffering ...")); + }, this); } void MainWindow::pause_cb () @@ -232,6 +251,8 @@ void MainWindow::pause_cb () void MainWindow::playback_stop_cb () { setWindowTitle ("Audacious"); + buffering_timer.stop (); + update_play_pause (); int last_list = aud_playlist_by_unique_id (playing_id); @@ -247,43 +268,43 @@ void MainWindow::update_toggles_cb () updateToggles (); } -struct DockWidget { - QDockWidget * w; - PluginHandle * pl; -}; +PluginWidget * MainWindow::find_dock_plugin (PluginHandle * plugin) +{ + for (PluginWidget * w : dock_widgets) + { + if (w->plugin () == plugin) + return w; + } + + return nullptr; +} void MainWindow::add_dock_plugin_cb (PluginHandle * plugin) { QWidget * widget = (QWidget *) aud_plugin_get_qt_widget (plugin); + if (! widget) + return; - if (widget) + auto w = find_dock_plugin (plugin); + if (! w) { - widget->resize (320, 240); + w = new PluginWidget (plugin); + dock_widgets.append (w); + } - auto w = new QDockWidget; - w->setWindowTitle (aud_plugin_get_name (plugin)); - w->setObjectName (aud_plugin_get_basename (plugin)); - w->setWidget (widget); - addDockWidget (Qt::LeftDockWidgetArea, w); + w->setWidget (widget); - dock_widgets.append (w, plugin); - } + if (! restoreDockWidget (w)) + addDockWidget (Qt::LeftDockWidgetArea, w); } void MainWindow::remove_dock_plugin_cb (PluginHandle * plugin) { - auto remove_cb = [&] (DockWidget & dw) + if (auto w = find_dock_plugin (plugin)) { - if (dw.pl != plugin) - return false; - - removeDockWidget (dw.w); - - delete dw.w; - return true; - }; - - dock_widgets.remove_if (remove_cb); + removeDockWidget (w); + delete w->widget (); + } } void MainWindow::add_dock_plugins () diff --git a/src/qtui/main_window.h b/src/qtui/main_window.h index 0c486eb..f24c0e5 100644 --- a/src/qtui/main_window.h +++ b/src/qtui/main_window.h @@ -22,20 +22,19 @@ #include <libaudcore/hook.h> #include <libaudcore/index.h> +#include <libaudcore/mainloop.h> #include <libaudcore/objects.h> #include "dialog_windows.h" #include "info_bar.h" #include <QMainWindow> -#include <QTimer> #include <QVBoxLayout> class FilterInput; class PlaylistTabs; class PluginHandle; - -struct DockWidget; +class PluginWidget; class MainWindow : public QMainWindow { @@ -55,7 +54,7 @@ private: QAction * toolButtonRepeat; QAction * toolButtonShuffle; - QTimer buffering_timer; + QueuedFunc buffering_timer; void closeEvent (QCloseEvent * e); void keyPressEvent (QKeyEvent * e); @@ -64,12 +63,10 @@ private: void setupActions (); void readSettings (); - void update_play_pause (); - void show_buffering (); - void add_dock_plugins (); void remove_dock_plugins (); + void update_play_pause (); void title_change_cb (); void playback_begin_cb (); void playback_ready_cb (); @@ -77,13 +74,14 @@ private: void playback_stop_cb (); void update_toggles_cb (); + PluginWidget * find_dock_plugin (PluginHandle * plugin); void add_dock_plugin_cb (PluginHandle * plugin); void remove_dock_plugin_cb (PluginHandle * plugin); const HookReceiver<MainWindow> hook1 {"title change", this, & MainWindow::title_change_cb}, hook2 {"playback begin", this, & MainWindow::playback_begin_cb}, - hook3 {"playback ready", this, & MainWindow::playback_ready_cb}, + hook3 {"playback ready", this, & MainWindow::title_change_cb}, hook4 {"playback pause", this, & MainWindow::pause_cb}, hook5 {"playback unpause", this, & MainWindow::pause_cb}, hook6 {"playback stop", this, & MainWindow::playback_stop_cb}, @@ -96,7 +94,7 @@ private: plugin_hook1 {"dock plugin enabled", this, & MainWindow::add_dock_plugin_cb}, plugin_hook2 {"dock plugin disabled", this, & MainWindow::remove_dock_plugin_cb}; - Index<DockWidget> dock_widgets; + Index<PluginWidget *> dock_widgets; int playing_id = -1; }; diff --git a/src/qtui/main_window_actions.cc b/src/qtui/main_window_actions.cc index 6e63257..d9f2bf8 100644 --- a/src/qtui/main_window_actions.cc +++ b/src/qtui/main_window_actions.cc @@ -25,7 +25,6 @@ #include <libaudcore/hook.h> #include <libaudcore/i18n.h> #include <libaudcore/runtime.h> -#include <libaudcore/plugin.h> #include <libaudcore/plugins.h> #include <libaudcore/drct.h> #include <libaudcore/interface.h> @@ -40,6 +39,8 @@ static void open_files () { audqt::fileopener_show (audqt::FileMode::Open); } static void add_files () { audqt::fileopener_show (audqt::FileMode::Add); } static void open_folder () { audqt::fileopener_show (audqt::FileMode::OpenFolder); } static void add_folder () { audqt::fileopener_show (audqt::FileMode::AddFolder); } +static void open_url () { audqt::urlopener_show (true); } +static void add_url () { audqt::urlopener_show (false); } static void rm_dupes_title () { aud_playlist_remove_duplicates_by_scheme (aud_playlist_get_active (), Playlist::Title); } static void rm_dupes_filename () { aud_playlist_remove_duplicates_by_scheme (aud_playlist_get_active (), Playlist::Filename); } @@ -71,15 +72,10 @@ static void sort_sel_custom_title () { aud_playlist_sort_by_scheme (aud_playlist static void sort_sel_reverse () { aud_playlist_reverse (aud_playlist_get_active ()); } static void sort_sel_random () { aud_playlist_randomize (aud_playlist_get_active ()); } -static void pl_new () -{ - aud_playlist_insert (-1); - aud_playlist_set_active (aud_playlist_count () - 1); -} - static void pl_play () { aud_playlist_play (aud_playlist_get_active ()); } static void pl_refresh () { aud_playlist_rescan (aud_playlist_get_active ()); } static void pl_remove_failed () { aud_playlist_remove_failed (aud_playlist_get_active ()); } +static void pl_rename () { hook_call ("qtui rename playlist", nullptr); } static void pl_close () { audqt::playlist_confirm_delete (aud_playlist_get_active ()); } static void volume_up () { aud_drct_set_volume_main (aud_drct_get_volume_main () + 5); } @@ -89,11 +85,13 @@ static void configure_effects () { audqt::prefswin_show_plugin_page (PluginType: void MainWindow::setupActions () { - static constexpr audqt::MenuItem file_items[] = { + static const audqt::MenuItem file_items[] = { audqt::MenuCommand ({N_("_Open Files ..."), "document-open", "Ctrl+O"}, open_files), audqt::MenuCommand ({N_("_Open Folder ..."), "document-open"}, open_folder), + audqt::MenuCommand ({N_("Open _URL ..."), "folder-remote", "Ctrl+L"}, open_url), audqt::MenuCommand ({N_("_Add Files ..."), "list-add", "Ctrl+Shift+O"}, add_files), audqt::MenuCommand ({N_("_Add Folder ..."), "list-add"}, add_folder), + audqt::MenuCommand ({N_("Add U_RL ..."), "folder-remote", "Ctrl+Shift+L"}, add_url), audqt::MenuSep (), audqt::MenuCommand ({N_("A_bout ..."), "help-about"}, aud_ui_show_about_window), audqt::MenuCommand ({N_("_Settings ..."), "preferences-system"}, aud_ui_show_prefs_window), @@ -103,28 +101,29 @@ void MainWindow::setupActions () audqt::MenuCommand ({N_("_Quit"), "application-exit", "Ctrl+Q"}, aud_quit) }; - static constexpr audqt::MenuItem playback_items[] = { + static const audqt::MenuItem playback_items[] = { audqt::MenuCommand ({N_("_Play"), "media-playback-start", "Ctrl+Return"}, aud_drct_play), audqt::MenuCommand ({N_("Paus_e"), "media-playback-pause", "Ctrl+,"}, aud_drct_pause), audqt::MenuCommand ({N_("_Stop"), "media-playback-stop", "Ctrl+."}, aud_drct_stop), audqt::MenuCommand ({N_("Pre_vious"), "media-skip-backward", "Alt+Up"}, aud_drct_pl_prev), audqt::MenuCommand ({N_("_Next"), "media-skip-forward", "Alt+Down"}, aud_drct_pl_next), audqt::MenuSep (), - audqt::MenuToggle ({N_("_Repeat"), nullptr, "Ctrl+R"}, {nullptr, "repeat", "set repeat"}), - audqt::MenuToggle ({N_("S_huffle"), nullptr, "Ctrl+S"}, {nullptr, "shuffle", "set shuffle"}), + audqt::MenuToggle ({N_("_Repeat"), "media-playlist-repeat", "Ctrl+R"}, {nullptr, "repeat", "set repeat"}), + audqt::MenuToggle ({N_("S_huffle"), "media-playlist-shuffle", "Ctrl+S"}, {nullptr, "shuffle", "set shuffle"}), + audqt::MenuToggle ({N_("Shuffle by Albu_m")}, {nullptr, "album_shuffle", "set album_shuffle"}), audqt::MenuToggle ({N_("N_o Playlist Advance"), nullptr, "Ctrl+N"}, {nullptr, "no_playlist_advance", "set no_playlist_advance"}), audqt::MenuToggle ({N_("Stop A_fter This Song"), nullptr, "Ctrl+M"}, {nullptr, "stop_after_current_song", "set stop_after_current_song"}), audqt::MenuSep (), audqt::MenuCommand ({N_("Song _Info ..."), "dialog-information", "Ctrl+I"}, audqt::infowin_show_current) }; - static constexpr audqt::MenuItem dupe_items[] = { + static const audqt::MenuItem dupe_items[] = { audqt::MenuCommand ({N_("By _Title")}, rm_dupes_title), audqt::MenuCommand ({N_("By _File Name")}, rm_dupes_filename), audqt::MenuCommand ({N_("By File _Path")}, rm_dupes_path), }; - static constexpr audqt::MenuItem sort_items[] = { + static const audqt::MenuItem sort_items[] = { audqt::MenuCommand ({N_("By Track _Number")}, sort_track), audqt::MenuCommand ({N_("By _Title")}, sort_title), audqt::MenuCommand ({N_("By _Artist")}, sort_artist), @@ -140,7 +139,7 @@ void MainWindow::setupActions () audqt::MenuCommand ({N_("_Random Order")}, sort_random) }; - static constexpr audqt::MenuItem sort_selected_items[] = { + static const audqt::MenuItem sort_selected_items[] = { audqt::MenuCommand ({N_("By Track _Number")}, sort_sel_track), audqt::MenuCommand ({N_("By _Title")}, sort_sel_title), audqt::MenuCommand ({N_("By _Artist")}, sort_sel_artist), @@ -156,7 +155,7 @@ void MainWindow::setupActions () audqt::MenuCommand ({N_("_Random Order")}, sort_sel_random) }; - static constexpr audqt::MenuItem playlist_items[] = { + static const audqt::MenuItem playlist_items[] = { audqt::MenuCommand ({N_("_Play/Resume"), "media-playback-start", "Shift+Return"}, pl_play), audqt::MenuCommand ({N_("_Refresh"), "view-refresh", "F5"}, pl_refresh), audqt::MenuSep (), @@ -165,8 +164,8 @@ void MainWindow::setupActions () audqt::MenuSub ({N_("Remove _Duplicates"), "edit-copy"}, dupe_items), audqt::MenuCommand ({N_("Remove _Unavailable Files"), "dialog-warning"}, pl_remove_failed), audqt::MenuSep (), - audqt::MenuCommand ({N_("_New"), "document-new", "Ctrl+T"}, pl_new), - //audqt::MenuCommand ({N_("Ren_ame ..."), "insert-text", "F2"}, TODO), + audqt::MenuCommand ({N_("_New"), "document-new", "Ctrl+T"}, (audqt::MenuFunc) aud_playlist_new), + audqt::MenuCommand ({N_("Ren_ame ..."), "insert-text", "F2"}, pl_rename), audqt::MenuCommand ({N_("Remo_ve"), "edit-delete", "Ctrl+W"}, pl_close), audqt::MenuSep (), //audqt::MenuCommand ({N_("_Import ..."), "document-open"}, TODO), @@ -176,16 +175,16 @@ void MainWindow::setupActions () audqt::MenuCommand ({N_("_Queue Manager ..."), nullptr, "Ctrl+U"}, audqt::queue_manager_show) }; - static constexpr audqt::MenuItem output_items[] = { + static const audqt::MenuItem output_items[] = { audqt::MenuCommand ({N_("Volume _Up"), "audio-volume-high", "Ctrl++"}, volume_up), audqt::MenuCommand ({N_("Volume _Down"), "audio-volume-low", "Ctrl+-"}, volume_down), audqt::MenuSep (), - audqt::MenuCommand ({N_("_Equalizer"), "multimedia-volume-control", "Ctrl+E"}, audqt::equalizer_show), + audqt::MenuCommand ({N_("_Equalizer ..."), "multimedia-volume-control", "Ctrl+E"}, audqt::equalizer_show), audqt::MenuSep (), audqt::MenuCommand ({N_("E_ffects ...")}, configure_effects) }; - static constexpr audqt::MenuItem main_items[] = { + static const audqt::MenuItem main_items[] = { audqt::MenuSub ({N_("_File")}, file_items), audqt::MenuSub ({N_("_Playback")}, playback_items), audqt::MenuSub ({N_("P_laylist")}, playlist_items), diff --git a/src/qtui/playlist.cc b/src/qtui/playlist.cc index 232336e..5a9a91e 100644 --- a/src/qtui/playlist.cc +++ b/src/qtui/playlist.cc @@ -24,6 +24,7 @@ #include <libaudcore/drct.h> #include <libaudcore/hook.h> #include <libaudcore/playlist.h> +#include <libaudcore/runtime.h> #include "playlist.h" #include "playlist_model.h" @@ -44,13 +45,21 @@ PlaylistWidget::PlaylistWidget (QTreeView * parent, int uniqueId) : QTreeView (p setUniformRowHeights (true); setFrameShape (QFrame::NoFrame); setSelectionMode (ExtendedSelection); + + updateSettings (); + + /* TODO: set column width based on font size */ setColumnWidth (PL_COL_NOW_PLAYING, 25); - setColumnWidth (PL_COL_TITLE, 300); - setColumnWidth (PL_COL_ARTIST, 150); - setColumnWidth (PL_COL_ALBUM, 200); - resizeColumnToContents (PL_COL_QUEUED); - resizeColumnToContents (PL_COL_LENGTH); - scrollToCurrent (); + setColumnWidth (PL_COL_TITLE, 275); + setColumnWidth (PL_COL_ARTIST, 175); + setColumnWidth (PL_COL_ALBUM, 175); + setColumnWidth (PL_COL_QUEUED, 25); + setColumnWidth (PL_COL_LENGTH, 50); + + /* get initial selection and focus from core */ + Playlist::Update upd {}; + upd.level = Playlist::Selection; + update (upd); } void PlaylistWidget::setFilter (const QString & text) @@ -80,12 +89,12 @@ int PlaylistWidget::indexToRow (const QModelIndex & index) return proxyModel->mapToSource (index).row (); } -void PlaylistWidget::keyPressEvent (QKeyEvent * e) +void PlaylistWidget::keyPressEvent (QKeyEvent * event) { - switch (e->modifiers ()) + switch (event->modifiers ()) { case Qt::NoModifier: - switch (e->key ()) + switch (event->key ()) { case Qt::Key_Escape: scrollToCurrent (); @@ -128,11 +137,26 @@ void PlaylistWidget::keyPressEvent (QKeyEvent * e) break; } - QTreeView::keyPressEvent (e); + QTreeView::keyPressEvent (event); +} + +void PlaylistWidget::mousePressEvent (QMouseEvent * event) +{ + QModelIndex index = indexAt (event->pos ()); + + if (! index.isValid ()) + return; + + QTreeView::mousePressEvent (event); } void PlaylistWidget::mouseDoubleClickEvent (QMouseEvent * event) { + QModelIndex index = indexAt (event->pos ()); + + if (! index.isValid ()) + return; + if (event->button () == Qt::LeftButton) playCurrentIndex (); } @@ -195,6 +219,41 @@ void PlaylistWidget::updatePlaybackIndicator () model->updateRows (currentPos, 1); } +void PlaylistWidget::getSelectedRanges (const Playlist::Update & update, + QItemSelection & selected, QItemSelection & deselected) +{ + int list = playlist (); + int entries = aud_playlist_entry_count (list); + + QItemSelection ranges[2]; + QModelIndex first, last; + bool prev = false; + + for (int row = update.before; row < entries - update.after; row ++) + { + auto idx = rowToIndex (row); + if (! idx.isValid ()) + continue; + + bool sel = aud_playlist_entry_get_selected (list, row); + + if (sel != prev && first.isValid ()) + ranges[prev].merge (QItemSelection (first, last), QItemSelectionModel::Select); + + if (sel != prev || ! first.isValid ()) + first = idx; + + last = idx; + prev = sel; + } + + if (first.isValid ()) + ranges[prev].merge (QItemSelection (first, last), QItemSelectionModel::Select); + + selected = std::move (ranges[true]); + deselected = std::move (ranges[false]); +} + void PlaylistWidget::update (const Playlist::Update & update) { inUpdate = true; @@ -242,15 +301,15 @@ void PlaylistWidget::update (const Playlist::Update & update) needIndicatorUpdate = false; } + QItemSelection selected, deselected; + getSelectedRanges (update, selected, deselected); + auto sel = selectionModel (); - for (int row = update.before; row < entries - update.after; row ++) - { - if (aud_playlist_entry_get_selected (list, row)) - sel->select (rowToIndex (row), sel->Select | sel->Rows); - else - sel->select (rowToIndex (row), sel->Deselect | sel->Rows); - } + if (! selected.isEmpty ()) + sel->select (selected, sel->Select | sel->Rows); + if (! deselected.isEmpty ()) + sel->select (deselected, sel->Deselect | sel->Rows); auto current = rowToIndex (aud_playlist_get_focus (list)); sel->setCurrentIndex (current, sel->NoUpdate); @@ -285,3 +344,8 @@ void PlaylistWidget::toggleQueue () else aud_playlist_queue_delete (playlist (), at, 1); } + +void PlaylistWidget::updateSettings () +{ + setHeaderHidden (! aud_get_bool ("qtui", "playlist_headers")); +} diff --git a/src/qtui/playlist.h b/src/qtui/playlist.h index a6bf161..e8523c0 100644 --- a/src/qtui/playlist.h +++ b/src/qtui/playlist.h @@ -21,6 +21,8 @@ #define PLAYLIST_H #include <QTreeView> + +#include <libaudcore/hook.h> #include <libaudcore/playlist.h> #include "playlist_model.h" @@ -38,7 +40,7 @@ public: void update (const Playlist::Update & update); void playCurrentIndex (); void deleteCurrentSelection (); - void setFilter (const QString &text); + void setFilter (const QString & text); void toggleQueue (); int playlist () const; int uniqueId () const; @@ -54,10 +56,18 @@ private: QModelIndex rowToIndex (int row); int indexToRow (const QModelIndex & index); - void keyPressEvent (QKeyEvent * e); /* override default handler */ + void getSelectedRanges (const Playlist::Update & update, + QItemSelection & selected, QItemSelection & deselected); + + void keyPressEvent (QKeyEvent * event); + void mousePressEvent (QMouseEvent * event); void mouseDoubleClickEvent (QMouseEvent * event); void currentChanged (const QModelIndex & current, const QModelIndex & previous); void selectionChanged (const QItemSelection & selected, const QItemSelection & deselected); + + void updateSettings (); + const HookReceiver<PlaylistWidget> + settings_hook {"qtui update playlist settings", this, & PlaylistWidget::updateSettings}; }; #endif diff --git a/src/qtui/playlist_model.cc b/src/qtui/playlist_model.cc index 98613ea..0d92cfd 100644 --- a/src/qtui/playlist_model.cc +++ b/src/qtui/playlist_model.cc @@ -36,16 +36,14 @@ static inline QPixmap get_icon (const char * name) return pm; } -PlaylistModel::PlaylistModel (QObject * parent, int id) : QAbstractListModel (parent), +PlaylistModel::PlaylistModel (QObject * parent, int id) : + QAbstractListModel (parent), m_uniqueId (id) { m_rows = aud_playlist_entry_count (playlist ()); } -PlaylistModel::~PlaylistModel () -{ - -} +PlaylistModel::~PlaylistModel () {} int PlaylistModel::rowCount (const QModelIndex & parent) const { @@ -88,6 +86,7 @@ QVariant PlaylistModel::data (const QModelIndex &index, int role) const case PL_COL_LENGTH: return QString (str_format_time (tuple.get_int (Tuple::Length))); } + break; case Qt::TextAlignmentRole: switch (index.column ()) @@ -95,6 +94,7 @@ QVariant PlaylistModel::data (const QModelIndex &index, int role) const case PL_COL_LENGTH: return Qt::AlignRight; } + break; case Qt::DecorationRole: if (index.column () == 0 && index.row () == aud_playlist_get_position (playlist ())) @@ -107,6 +107,7 @@ QVariant PlaylistModel::data (const QModelIndex &index, int role) const else return get_icon ("media-playback-stop"); } + break; } return QVariant (); } @@ -147,6 +148,9 @@ int PlaylistModel::uniqueId () const bool PlaylistModel::insertRows (int row, int count, const QModelIndex & parent) { + if (count < 1) + return true; + int last = row + count - 1; beginInsertRows (parent, row, last); m_rows = aud_playlist_entry_count (playlist ()); @@ -156,6 +160,9 @@ bool PlaylistModel::insertRows (int row, int count, const QModelIndex & parent) bool PlaylistModel::removeRows (int row, int count, const QModelIndex & parent) { + if (count < 1) + return true; + int last = row + count - 1; beginRemoveRows (parent, row, last); m_rows = aud_playlist_entry_count (playlist ()); @@ -165,6 +172,9 @@ bool PlaylistModel::removeRows (int row, int count, const QModelIndex & parent) void PlaylistModel::updateRows (int row, int count) { + if (count < 1) + return; + int bottom = row + count - 1; auto topLeft = createIndex (row, 0); auto bottomRight = createIndex (bottom, columnCount () - 1); @@ -175,7 +185,7 @@ QString PlaylistModel::getQueued (int row) const { int at = aud_playlist_queue_find_entry (playlist (), row); if (at < 0) - return QString (""); + return QString (); else return QString ("#%1").arg (at + 1); } diff --git a/src/qtui/playlist_tabs.cc b/src/qtui/playlist_tabs.cc index f82e76a..68632c5 100644 --- a/src/qtui/playlist_tabs.cc +++ b/src/qtui/playlist_tabs.cc @@ -39,66 +39,73 @@ PlaylistTabs::PlaylistTabs (QWidget * parent) : m_tabbar->setFocusPolicy (Qt::NoFocus); setTabBar (m_tabbar); - populatePlaylists (); + addRemovePlaylists (); + updateTitles (); setCurrentIndex (aud_playlist_get_active ()); - connect (this, &QTabWidget::currentChanged, this, &PlaylistTabs::currentChangedTrigger); + connect (this, & QTabWidget::currentChanged, this, & PlaylistTabs::currentChangedTrigger); } -PlaylistTabs::~PlaylistTabs () -{ - // TODO: cleanup playlists -} - -void PlaylistTabs::maybeCreateTab (int count_, int uniq_id) +void PlaylistTabs::addRemovePlaylists () { int tabs = count (); + int playlists = aud_playlist_count (); - for (int i = 0; i < tabs; i++) + for (int i = 0; i < tabs; i ++) { - PlaylistWidget * playlistWidget = (PlaylistWidget *) widget (i); - if (uniq_id == playlistWidget->uniqueId()) - return; - } - - auto playlistWidget = new PlaylistWidget (0, uniq_id); - addTab ((QWidget *) playlistWidget, QString (aud_playlist_get_title (count_))); -} + auto widget = playlistWidget (i); + int playlist = widget->playlist (); -void PlaylistTabs::cullPlaylists () -{ - int tabs = count (); + if (playlist < 0) + { + removeTab (i); + delete widget; + tabs --; + i --; + } + else if (playlist != i) + { + bool found = false; + + for (int j = i + 1; j < tabs; j ++) + { + widget = playlistWidget (j); + playlist = widget->playlist (); + + if (playlist == i) + { + removeTab (j); + insertTab (i, widget, QString ()); + found = true; + break; + } + } + + if (! found) + { + int id = aud_playlist_get_unique_id (i); + insertTab (i, new PlaylistWidget (0, id), QString ()); + tabs ++; + } + } + } - for (int i = 0; i < tabs; i++) + while (tabs < playlists) { - PlaylistWidget * playlistWidget = (PlaylistWidget *) widget (i); - - if (playlistWidget == nullptr || playlistWidget->playlist() < 0) - { - removeTab(i); - delete playlistWidget; - } - else - setTabText(i, QString (aud_playlist_get_title (playlistWidget->playlist()))); + int id = aud_playlist_get_unique_id (tabs); + addTab (new PlaylistWidget (0, id), QString ()); + tabs ++; } } -void PlaylistTabs::populatePlaylists () +void PlaylistTabs::updateTitles () { - int playlists = aud_playlist_count (); - - for (int count = 0; count < playlists; count++) - maybeCreateTab(count, aud_playlist_get_unique_id (count)); - - cullPlaylists(); -} - -PlaylistWidget * PlaylistTabs::playlistWidget (int num) -{ - return (PlaylistWidget *) widget (num); + int tabs = count (); + for (int i = 0; i < tabs; i ++) + setTabTitle (i, aud_playlist_get_title (i)); } -void PlaylistTabs::filterTrigger (const QString &text) +void PlaylistTabs::filterTrigger (const QString & text) { ((PlaylistWidget *) currentWidget ())->setFilter (text); } @@ -114,11 +121,25 @@ QLineEdit * PlaylistTabs::getTabEdit (int idx) return dynamic_cast<QLineEdit *> (m_tabbar->tabButton (idx, QTabBar::LeftSide)); } -void PlaylistTabs::setupTab (int idx, QWidget * button, const QString & text, QWidget * * oldp) +void PlaylistTabs::setTabTitle (int idx, const char * text) +{ + QString title = QString (); + + if (aud_get_bool ("qtui", "entry_count_visible")) + { + title.setNum (aud_playlist_entry_count (idx)); + title.prepend (" (").append (")"); + } + + // escape ampersands for setTabText () + setTabText (idx, title.prepend (QString (text).replace ("&", "&&"))); +} + +void PlaylistTabs::setupTab (int idx, QWidget * button, const char * text, QWidget * * oldp) { QWidget * old = m_tabbar->tabButton (idx, QTabBar::LeftSide); m_tabbar->setTabButton (idx, QTabBar::LeftSide, button); - setTabText (idx, text); + setTabTitle (idx, text); if (oldp) * oldp = old; @@ -139,8 +160,8 @@ void PlaylistTabs::tabEditedTrigger () if (! edit) return; - QString title = edit->text (); - aud_playlist_set_title (idx, title.toUtf8 ()); + QByteArray title = edit->text ().toUtf8 (); + aud_playlist_set_title (idx, title); setupTab (idx, m_leftbtn, title, nullptr); m_leftbtn = nullptr; @@ -148,11 +169,17 @@ void PlaylistTabs::tabEditedTrigger () void PlaylistTabs::editTab (int idx) { - QLineEdit * edit = new QLineEdit (tabText (idx)); + QLineEdit * edit = getTabEdit (idx); - connect (edit, & QLineEdit::returnPressed, this, & PlaylistTabs::tabEditedTrigger); + if (! edit) + { + edit = new QLineEdit ((const char *) aud_playlist_get_title (idx)); - setupTab (idx, edit, QString (), & m_leftbtn); + connect (edit, & QLineEdit::returnPressed, this, & PlaylistTabs::tabEditedTrigger); + + setupTab (idx, edit, nullptr, & m_leftbtn); + setTabText (idx, nullptr); + } edit->selectAll (); edit->setFocus (); @@ -162,9 +189,9 @@ bool PlaylistTabs::eventFilter (QObject * obj, QEvent * e) { if (e->type() == QEvent::KeyPress) { - QKeyEvent *ke = (QKeyEvent *) e; + QKeyEvent * ke = (QKeyEvent *) e; - if (ke->key() == Qt::Key_Escape) + if (ke->key () == Qt::Key_Escape) { cancelRename (); return true; @@ -174,6 +201,16 @@ bool PlaylistTabs::eventFilter (QObject * obj, QEvent * e) return QTabWidget::eventFilter(obj, e); } +void PlaylistTabs::renameCurrent () +{ + int idx = currentIndex (); + + if (! m_tabbar->isVisible ()) + audqt::playlist_show_rename (idx); + else + editTab (idx); +} + void PlaylistTabs::cancelRename () { for (int i = 0; i < count (); i ++) @@ -187,10 +224,18 @@ void PlaylistTabs::cancelRename () } } +void PlaylistTabs::playlist_activate_cb () +{ + if (! aud_playlist_update_pending ()) + setCurrentIndex (aud_playlist_get_active ()); +} + void PlaylistTabs::playlist_update_cb (Playlist::UpdateLevel global_level) { if (global_level == Playlist::Structure) - populatePlaylists (); + addRemovePlaylists (); + if (global_level >= Playlist::Metadata) + updateTitles (); int lists = aud_playlist_count (); for (int list = 0; list < lists; list ++) @@ -199,6 +244,8 @@ void PlaylistTabs::playlist_update_cb (Playlist::UpdateLevel global_level) if (update.level) playlistWidget (list)->update (update); } + + setCurrentIndex (aud_playlist_get_active ()); } void PlaylistTabs::playlist_position_cb (int list) @@ -210,30 +257,58 @@ void PlaylistTabs::playlist_position_cb (int list) PlaylistTabBar::PlaylistTabBar (QWidget * parent) : QTabBar (parent) { + setMovable (true); setDocumentMode (true); - setTabsClosable (true); + updateSettings (); - connect (this, &QTabBar::tabCloseRequested, this, &PlaylistTabBar::handleCloseRequest); + connect (this, & QTabBar::tabMoved, this, & PlaylistTabBar::tabMoved); + connect (this, & QTabBar::tabCloseRequested, this, & PlaylistTabBar::handleCloseRequest); } -void PlaylistTabBar::mouseDoubleClickEvent (QMouseEvent *e) +void PlaylistTabBar::tabMoved (int from, int to) { - PlaylistTabs *p = (PlaylistTabs *) parent(); + aud_playlist_reorder (from, to, 1); +} - int idx = tabAt (e->pos()); - if (idx < 0) +void PlaylistTabBar::mousePressEvent (QMouseEvent * e) +{ + if (e->button () == Qt::MidButton) + { + int index = tabAt (e->pos ()); + handleCloseRequest (index); + e->accept (); + } + + QTabBar::mousePressEvent (e); +} + +void PlaylistTabBar::mouseDoubleClickEvent (QMouseEvent * e) +{ + int idx = tabAt (e->pos ()); + if (idx < 0 || e->button () != Qt::LeftButton) return; - p->editTab (idx); + PlaylistTabs * p = (PlaylistTabs *) parent (); + PlaylistWidget * pl = p->playlistWidget (idx); + + aud_playlist_play (pl->playlist ()); } void PlaylistTabBar::handleCloseRequest (int idx) { - PlaylistTabs *p = (PlaylistTabs *) parent (); - PlaylistWidget *pl = (PlaylistWidget *) p->widget (idx); + PlaylistTabs * p = (PlaylistTabs *) parent (); + PlaylistWidget * pl = p->playlistWidget (idx); if (! pl) return; audqt::playlist_confirm_delete (pl->playlist ()); } + +void PlaylistTabBar::updateSettings () +{ +#if QT_VERSION >= 0x050400 + setAutoHide (! aud_get_bool ("qtui", "playlist_tabs_visible")); +#endif + setTabsClosable (aud_get_bool ("qtui", "close_button_visible")); +} diff --git a/src/qtui/playlist_tabs.h b/src/qtui/playlist_tabs.h index f9384a9..1aff1e0 100644 --- a/src/qtui/playlist_tabs.h +++ b/src/qtui/playlist_tabs.h @@ -36,37 +36,45 @@ class PlaylistTabs : public QTabWidget { public: PlaylistTabs (QWidget * parent = nullptr); - ~PlaylistTabs (); - PlaylistWidget * playlistWidget (int num); + PlaylistWidget * playlistWidget (int num) + { return (PlaylistWidget *) widget (num); } void editTab (int idx); - void filterTrigger (const QString &text); + void filterTrigger (const QString & text); void currentChangedTrigger (int idx); void tabEditedTrigger (); protected: - bool eventFilter (QObject * obj, QEvent *e); + bool eventFilter (QObject * obj, QEvent * e); private: - QWidget *m_leftbtn; - PlaylistTabBar *m_tabbar; + QWidget * m_leftbtn; + PlaylistTabBar * m_tabbar; QLineEdit * getTabEdit (int idx); - void setupTab (int idx, QWidget * button, const QString & text, QWidget * * oldp); + void setTabTitle (int idx, const char * text); + void setupTab (int idx, QWidget * button, const char * text, QWidget * * oldp); - void populatePlaylists (); - void maybeCreateTab (int count_, int uniq_id); - void cullPlaylists (); + void addRemovePlaylists (); + void updateTitles (); + void renameCurrent (); void cancelRename (); + void playlist_activate_cb (); void playlist_update_cb (Playlist::UpdateLevel global_level); void playlist_position_cb (int list); + const HookReceiver<PlaylistTabs> + activate_hook {"playlist activate", this, & PlaylistTabs::playlist_activate_cb}; const HookReceiver<PlaylistTabs, Playlist::UpdateLevel> update_hook {"playlist update", this, & PlaylistTabs::playlist_update_cb}; const HookReceiver<PlaylistTabs, int> position_hook {"playlist position", this, & PlaylistTabs::playlist_position_cb}; + const HookReceiver<PlaylistTabs> + rename_hook {"qtui rename playlist", this, & PlaylistTabs::renameCurrent}; + const HookReceiver<PlaylistTabs> + settings_hook {"qtui update playlist settings", this, & PlaylistTabs::updateTitles}; }; class PlaylistTabBar : public QTabBar @@ -76,7 +84,15 @@ public: void handleCloseRequest (int idx); protected: - void mouseDoubleClickEvent (QMouseEvent *e); + void tabMoved (int from, int to); + void mousePressEvent (QMouseEvent * e); + void mouseDoubleClickEvent (QMouseEvent * e); + +private: + void updateSettings (); + + const HookReceiver<PlaylistTabBar> + settings_hook {"qtui update playlist settings", this, & PlaylistTabBar::updateSettings}; }; #endif diff --git a/src/qtui/qtui.cc b/src/qtui/qtui.cc index 24c86c1..c410cdb 100644 --- a/src/qtui/qtui.cc +++ b/src/qtui/qtui.cc @@ -19,6 +19,7 @@ #include <QApplication> +#define AUD_PLUGIN_QT_ONLY #include <libaudcore/i18n.h> #include <libaudcore/plugin.h> #include <libaudcore/runtime.h> @@ -27,29 +28,21 @@ #include <libaudqt/iface.h> #include "main_window.h" - -static char app_name[] = "audacious"; -static int dummy_argc = 1; -static char * dummy_argv[] = {app_name, nullptr}; +#include "settings.h" class QtUI : public audqt::QtIfacePlugin { private: - QApplication * qapp = nullptr; MainWindow * window = nullptr; public: - constexpr QtUI () : audqt::QtIfacePlugin ({N_("Qt Interface"), PACKAGE}) {} + constexpr QtUI () : audqt::QtIfacePlugin ({N_("Qt Interface"), PACKAGE, nullptr, & qtui_prefs}) {} bool init () { - if (aud_get_mainloop_type () != MainloopType::Qt) - return false; - - qapp = new QApplication (dummy_argc, dummy_argv); - qapp->setAttribute(Qt::AA_UseHighDpiPixmaps); + audqt::init (); + aud_config_set_defaults ("qtui", qtui_defaults); window = new MainWindow; - return true; } @@ -57,16 +50,12 @@ public: { delete window; window = nullptr; - audqt::cleanup (); - - delete qapp; - qapp = nullptr; } void run () { - qapp->exec (); + audqt::run (); } void show (bool show) @@ -76,7 +65,7 @@ public: void quit () { - qapp->quit(); + audqt::quit (); } }; diff --git a/src/qtui/settings.cc b/src/qtui/settings.cc new file mode 100644 index 0000000..7f43508 --- /dev/null +++ b/src/qtui/settings.cc @@ -0,0 +1,74 @@ +/* + * settings.cc + * Copyright 2015 Eugene Paskevich + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions, and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions, and the following disclaimer in the documentation + * provided with the distribution. + * + * This software is provided "as is" and without any warranty, express or + * implied. In no event shall the authors be liable for any damages arising from + * the use of this software. + */ + +#include "settings.h" + +#include <libaudcore/hook.h> +#include <libaudcore/i18n.h> +#include <libaudcore/preferences.h> + +#include <QtGlobal> + +const char * const qtui_defaults[] = { +// "infoarea_show_vis", "TRUE", +// "infoarea_visible", "TRUE", +// "menu_visible", "TRUE", + "playlist_tabs_visible", "TRUE", +// "statusbar_visible", "TRUE", + "entry_count_visible", "FALSE", + "close_button_visible", "TRUE", + +// "autoscroll", "TRUE", +// "playlist_columns", "title artist album queued length", + "playlist_headers", "TRUE", +// "record", "FALSE", +// "show_remaining_time", "FALSE", +// "step_size", "5", + + nullptr +}; + +static void qtui_update_playlist_settings () +{ + hook_call ("qtui update playlist settings", nullptr); +} + +static const PreferencesWidget qtui_widgets[] = { + WidgetLabel (N_("<b>Playlist Tabs</b>")), +#if QT_VERSION >= 0x050400 + WidgetCheck (N_("Always show tabs"), + WidgetBool ("qtui", "playlist_tabs_visible", qtui_update_playlist_settings)), +#endif + WidgetCheck (N_("Show entry counts"), + WidgetBool ("qtui", "entry_count_visible", qtui_update_playlist_settings)), + WidgetCheck (N_("Show close buttons"), + WidgetBool ("qtui", "close_button_visible", qtui_update_playlist_settings)), + WidgetLabel (N_("<b>Playlist Columns</b>")), +// WidgetCustomQt (pw_col_create_chooser), + WidgetCheck (N_("Show column headers"), + WidgetBool ("qtui", "playlist_headers", qtui_update_playlist_settings)), +// WidgetLabel (N_("<b>Miscellaneous</b>")), +// WidgetSpin (N_("Arrow keys seek by:"), +// WidgetFloat ("qtui", "step_size", update_step_size), +// {0.1, 60, 0.1, N_("seconds")}), +// WidgetCheck (N_("Scroll on song change"), +// WidgetBool ("qtui", "autoscroll")) +}; + +const PluginPreferences qtui_prefs = {{qtui_widgets}}; diff --git a/src/qtui/settings.h b/src/qtui/settings.h new file mode 100644 index 0000000..c0bca19 --- /dev/null +++ b/src/qtui/settings.h @@ -0,0 +1,28 @@ +/* + * settings.h + * Copyright 2015 Eugene Paskevich + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions, and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions, and the following disclaimer in the documentation + * provided with the distribution. + * + * This software is provided "as is" and without any warranty, express or + * implied. In no event shall the authors be liable for any damages arising from + * the use of this software. + */ + +#ifndef SETTINGS_H +#define SETTINGS_H + +struct PluginPreferences; +extern const PluginPreferences qtui_prefs; + +extern const char * const qtui_defaults[]; + +#endif diff --git a/src/qtui/status_bar.cc b/src/qtui/status_bar.cc index 3856ffa..35f4632 100644 --- a/src/qtui/status_bar.cc +++ b/src/qtui/status_bar.cc @@ -76,7 +76,7 @@ void StatusBar::update_codec () if (samplerate > 0) { - buf.combine (str_printf ("%d kHz", samplerate / 1000)); + buf.combine (str_printf (_("%d kHz"), samplerate / 1000)); if (bitrate > 0) buf.insert (-1, ", "); } diff --git a/src/qtui/status_bar.h b/src/qtui/status_bar.h index 1cdece5..5e2c139 100644 --- a/src/qtui/status_bar.h +++ b/src/qtui/status_bar.h @@ -46,4 +46,4 @@ private: hook6 {"tuple change", this, & StatusBar::update_codec}; }; -#endif // STATUS_BAR_H +#endif diff --git a/src/qtui/time_slider.cc b/src/qtui/time_slider.cc index dee7d47..8211991 100644 --- a/src/qtui/time_slider.cc +++ b/src/qtui/time_slider.cc @@ -32,7 +32,6 @@ TimeSlider::TimeSlider (QWidget * parent) : m_label->setContentsMargins (4, 0, 4, 0); m_label->setSizePolicy (QSizePolicy::Fixed, QSizePolicy::MinimumExpanding); - connect (& m_timer, & QTimer::timeout, this, & TimeSlider::update); connect (this, & QSlider::valueChanged, this, & TimeSlider::moved); connect (this, & QSlider::sliderPressed, this, & TimeSlider::pressed); connect (this, & QSlider::sliderReleased, this, & TimeSlider::released); @@ -74,7 +73,7 @@ void TimeSlider::start_stop () } if (ready && ! paused && ! isSliderDown ()) - m_timer.start (250); + m_timer.start (); else m_timer.stop (); } @@ -106,7 +105,7 @@ void TimeSlider::released () set_label (value (), aud_drct_get_length ()); if (! aud_drct_get_paused ()) - m_timer.start (250); + m_timer.start (); } void TimeSlider::mousePressEvent (QMouseEvent * event) diff --git a/src/qtui/time_slider.h b/src/qtui/time_slider.h index f0a82bf..c6c90f8 100644 --- a/src/qtui/time_slider.h +++ b/src/qtui/time_slider.h @@ -22,7 +22,6 @@ #include <QLabel> #include <QSlider> -#include <QTimer> #include <QStyle> #include <QMouseEvent> @@ -48,9 +47,11 @@ private: void mousePressEvent (QMouseEvent * event); - QTimer m_timer; QLabel * m_label; + const Timer<TimeSlider> + m_timer {TimerRate::Hz4, this, & TimeSlider::update}; + const HookReceiver<TimeSlider> hook1 {"playback ready", this, & TimeSlider::start_stop}, hook2 {"playback pause", this, & TimeSlider::start_stop}, @@ -58,4 +59,4 @@ private: hook4 {"playback stop", this, & TimeSlider::start_stop}; }; -#endif // TIME_SLIDER_H +#endif diff --git a/src/qtui/tool_bar.cc b/src/qtui/tool_bar.cc index 1d67ff0..348bbbd 100644 --- a/src/qtui/tool_bar.cc +++ b/src/qtui/tool_bar.cc @@ -30,9 +30,12 @@ ToolBar::ToolBar (QWidget * parent, ArrayRef<ToolBarItem> items) { setContextMenuPolicy (Qt::PreventContextMenu); setMovable (false); - setIconSize (QSize (22, 22)); setObjectName ("MainToolBar"); +#if defined(Q_OS_WIN32) || defined(Q_OS_MAC) + setIconSize (QSize (22, 22)); +#endif + for (const ToolBarItem & item : items) { if (item.widget) @@ -48,12 +51,12 @@ ToolBar::ToolBar (QWidget * parent, ArrayRef<ToolBarItem> items) a->setToolTip (audqt::translate_str (item.tooltip_text)); if (item.callback) - connect (a, &QAction::triggered, item.callback); + connect (a, & QAction::triggered, item.callback); if (item.toggled) { a->setCheckable (true); - connect (a, &QAction::toggled, item.toggled); + connect (a, & QAction::toggled, item.toggled); } addAction (a); diff --git a/src/qtui/tool_bar.h b/src/qtui/tool_bar.h index 31d3126..2ad972b 100644 --- a/src/qtui/tool_bar.h +++ b/src/qtui/tool_bar.h @@ -24,8 +24,7 @@ #include <libaudcore/objects.h> -struct ToolBarItem -{ +struct ToolBarItem { const char * icon_name; const char * name; const char * tooltip_text; @@ -46,12 +45,12 @@ public: ToolBar (QWidget * parent, ArrayRef<ToolBarItem> items); }; -constexpr ToolBarItem ToolBarAction (const char * icon_name, const char * name, const char * tooltip_text, - void (* callback) (), QAction * * action_ptr = nullptr) +constexpr ToolBarItem ToolBarAction (const char * icon_name, const char * name, + const char * tooltip_text, void (* callback) (), QAction * * action_ptr = nullptr) { return { icon_name, name, tooltip_text, callback, nullptr, nullptr, false, action_ptr }; } -constexpr ToolBarItem ToolBarAction (const char * icon_name, const char * name, const char * tooltip_text, - void (* toggled) (bool), QAction * * action_ptr = nullptr) +constexpr ToolBarItem ToolBarAction (const char * icon_name, const char * name, + const char * tooltip_text, void (* toggled) (bool), QAction * * action_ptr = nullptr) { return { icon_name, name, tooltip_text, nullptr, toggled, nullptr, false, action_ptr }; } constexpr ToolBarItem ToolBarCustom (QWidget * item) diff --git a/src/scrobbler2/config_window.cc b/src/scrobbler2/config_window.cc index c122f62..2b228f5 100644 --- a/src/scrobbler2/config_window.cc +++ b/src/scrobbler2/config_window.cc @@ -6,8 +6,8 @@ //shared variables -gboolean permission_check_requested = FALSE; -gboolean invalidate_session_requested = FALSE; +gboolean permission_check_requested = false; +gboolean invalidate_session_requested = false; enum permission perm_result = PERMISSION_UNKNOWN; String username; @@ -27,9 +27,9 @@ static GtkWidget *additional_details_label; static gboolean permission_checker_thread (void * data) { - if (permission_check_requested == TRUE) { + if (permission_check_requested == true) { //the answer hasn't arrived yet - return TRUE; + return true; } else { //the answer has arrived @@ -42,7 +42,7 @@ static gboolean permission_checker_thread (void * data) { (const char *)username); gtk_label_set_markup(GTK_LABEL(permission_status_label), markup); - gtk_widget_set_sensitive(revoke_button, TRUE); + gtk_widget_set_sensitive(revoke_button, true); g_free(markup); } else if (perm_result == PERMISSION_DENIED) { @@ -82,16 +82,16 @@ static gboolean permission_checker_thread (void * data) { } perm_result = PERMISSION_UNKNOWN; - gtk_widget_set_sensitive(button, TRUE); + gtk_widget_set_sensitive(button, true); - return FALSE; + return false; } } static void cleanup_window() { - gtk_widget_set_sensitive(button, FALSE); - gtk_widget_set_sensitive(revoke_button, FALSE); + gtk_widget_set_sensitive(button, false); + gtk_widget_set_sensitive(revoke_button, false); gtk_image_clear(GTK_IMAGE(permission_status_icon)); gtk_image_clear(GTK_IMAGE(additional_details_icon)); @@ -111,11 +111,11 @@ static void permission_checker (GtkButton *button12, void * data) { //This will make the communication thread check the permission //and set the current status on the perm_result enum - permission_check_requested = TRUE; + permission_check_requested = true; //This is only to accelerate the check. //If scrobbles are being made, they are stopped for the request to be done sooner. - scrobbling_enabled = FALSE; + scrobbling_enabled = false; //Wake up the communication thread in case it's waiting for track plays pthread_mutex_lock(&communication_mutex); @@ -130,13 +130,13 @@ static void revoke_permissions (GtkButton *revoke_button2, void * data) { cleanup_window(); pthread_mutex_lock(&communication_mutex); - invalidate_session_requested = TRUE; + invalidate_session_requested = true; - scrobbling_enabled = FALSE; + scrobbling_enabled = false; pthread_cond_signal(&communication_signal); pthread_mutex_unlock(&communication_mutex); - gtk_widget_set_sensitive(button, TRUE); + gtk_widget_set_sensitive(button, true); } /* @@ -167,15 +167,15 @@ static void *config_status_checker () { GtkWidget *details_box; GtkWidget *additional_details_box; - config_box = gtk_vbox_new (FALSE, 15); - permission_box = gtk_hbox_new (FALSE, 0); + config_box = gtk_vbox_new (false, 15); + permission_box = gtk_hbox_new (false, 0); buttons_box = gtk_vbutton_box_new (); - details_box = gtk_vbox_new (FALSE, 0); - additional_details_box = gtk_hbox_new (FALSE, 7); + details_box = gtk_vbox_new (false, 0); + additional_details_box = gtk_hbox_new (false, 7); button = gtk_button_new_with_mnemonic(_("C_heck Permission")); revoke_button = gtk_button_new_with_mnemonic(_("_Revoke Permission")); - gtk_widget_set_sensitive(revoke_button, FALSE); + gtk_widget_set_sensitive(revoke_button, false); permission_status_icon = gtk_image_new(); permission_status_label = gtk_label_new(""); @@ -185,7 +185,7 @@ static void *config_status_checker () { details_label_second = gtk_label_new(""); gtk_widget_hide(url_button); - gtk_widget_set_no_show_all(url_button, TRUE); + gtk_widget_set_no_show_all(url_button, true); additional_details_icon = gtk_image_new(); additional_details_label = gtk_label_new(""); @@ -194,23 +194,23 @@ static void *config_status_checker () { g_signal_connect (button, "clicked", G_CALLBACK (permission_checker), nullptr); g_signal_connect (revoke_button, "clicked", G_CALLBACK (revoke_permissions), nullptr); - gtk_box_pack_start(GTK_BOX(permission_box), buttons_box, FALSE, FALSE, 20); - gtk_box_pack_start(GTK_BOX(permission_box), permission_status_icon, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(permission_box), permission_status_label, FALSE, FALSE, 5); + gtk_box_pack_start(GTK_BOX(permission_box), buttons_box, false, false, 20); + gtk_box_pack_start(GTK_BOX(permission_box), permission_status_icon, false, false, 0); + gtk_box_pack_start(GTK_BOX(permission_box), permission_status_label, false, false, 5); - gtk_box_pack_start(GTK_BOX(buttons_box), button, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(buttons_box), revoke_button, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(buttons_box), button, false, false, 0); + gtk_box_pack_start(GTK_BOX(buttons_box), revoke_button, false, false, 0); - gtk_box_pack_start(GTK_BOX(details_box), details_label_first, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(details_box), url_button, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(details_box), details_label_second, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(details_box), details_label_first, false, false, 0); + gtk_box_pack_start(GTK_BOX(details_box), url_button, false, false, 0); + gtk_box_pack_start(GTK_BOX(details_box), details_label_second, false, false, 0); - gtk_box_pack_start(GTK_BOX(additional_details_box), additional_details_icon, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(additional_details_box), additional_details_label, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(additional_details_box), additional_details_icon, false, false, 0); + gtk_box_pack_start(GTK_BOX(additional_details_box), additional_details_label, false, false, 0); - gtk_box_pack_start(GTK_BOX(config_box), permission_box, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(config_box), details_box, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(config_box), additional_details_box, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(config_box), permission_box, false, false, 0); + gtk_box_pack_start(GTK_BOX(config_box), details_box, false, false, 0); + gtk_box_pack_start(GTK_BOX(config_box), additional_details_box, false, false, 0); return config_box; } diff --git a/src/scrobbler2/scrobbler.cc b/src/scrobbler2/scrobbler.cc index f930b68..c019595 100644 --- a/src/scrobbler2/scrobbler.cc +++ b/src/scrobbler2/scrobbler.cc @@ -41,9 +41,9 @@ public: EXPORT Scrobbler aud_plugin_instance; //shared variables -gboolean scrobbler_running = TRUE; -gboolean migrate_config_requested = FALSE; -gboolean now_playing_requested = FALSE; +gboolean scrobbler_running = true; +gboolean migrate_config_requested = false; +gboolean now_playing_requested = false; Tuple now_playing_track; pthread_mutex_t communication_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -64,7 +64,7 @@ static unsigned queue_function_ID = 0; static pthread_t communicator; -static void cleanup_current_track(void) { +static void cleanup_current_track () { timestamp = 0; play_started_at = 0; @@ -126,7 +126,7 @@ static gboolean queue_track_to_scrobble (void * data) { } g_free(queuepath); cleanup_current_track(); - return FALSE; + return false; } @@ -168,7 +168,7 @@ static void ready (void *hook_data, void *user_data) { pthread_mutex_lock(&communication_mutex); now_playing_track = current_track.ref (); - now_playing_requested = TRUE; + now_playing_requested = true; pthread_cond_signal(&communication_signal); pthread_mutex_unlock(&communication_mutex); @@ -220,15 +220,15 @@ bool Scrobbler::init () // the version it was compiled for and the actual libXML in use LIBXML_TEST_VERSION - if (scrobbler_communication_init() == FALSE) { + if (scrobbler_communication_init() == false) { aud_ui_show_error(_("The Scrobbler plugin could not be started.\n" "There might be a problem with your installation.")); - return FALSE; + return false; } session_key = aud_get_str("scrobbler", "session_key"); if (!session_key[0]) - scrobbling_enabled = FALSE; + scrobbling_enabled = false; //TODO: Remove this after we are "sure" that noone is using the old scrobbler (from audacious < 3.4) //By Debian's standard, this will probably be by 2020 or so @@ -245,8 +245,8 @@ bool Scrobbler::init () if (oldpass[0] && olduser[0]) { //And the old scrobbler was configured - scrobbling_enabled = FALSE; - migrate_config_requested = TRUE; + scrobbling_enabled = false; + migrate_config_requested = true; } } } @@ -258,7 +258,7 @@ bool Scrobbler::init () hook_associate("playback ready", (HookFunction) ready, nullptr); hook_associate("playback pause", (HookFunction) paused, nullptr); hook_associate("playback unpause", (HookFunction) unpaused, nullptr); - return TRUE; + return true; } void Scrobbler::cleanup () @@ -271,8 +271,8 @@ void Scrobbler::cleanup () cleanup_current_track(); - scrobbling_enabled = FALSE; - scrobbler_running = FALSE; + scrobbling_enabled = false; + scrobbler_running = false; pthread_mutex_lock(&communication_mutex); pthread_cond_signal(&communication_signal); pthread_mutex_unlock(&communication_mutex); @@ -282,7 +282,7 @@ void Scrobbler::cleanup () request_token = String(); session_key = String(); username = String(); - scrobbler_running = TRUE; + scrobbler_running = true; } const char Scrobbler::about[] = diff --git a/src/scrobbler2/scrobbler_communication.cc b/src/scrobbler2/scrobbler_communication.cc index 4e4d549..e842230 100644 --- a/src/scrobbler2/scrobbler_communication.cc +++ b/src/scrobbler2/scrobbler_communication.cc @@ -20,7 +20,7 @@ typedef struct { static CURL *curlHandle = nullptr; //global handle holding cURL options -gboolean scrobbling_enabled = TRUE; +gboolean scrobbling_enabled = true; //shared variables char *received_data = nullptr; //Holds the result of the last request made to last.fm @@ -126,10 +126,10 @@ static gboolean send_message_to_lastfm (const char * data) if (curl_requests_result != CURLE_OK) { AUDDBG("Could not communicate with last.fm: %s.\n", curl_easy_strerror(curl_requests_result)); - return FALSE; + return false; } - return TRUE; + return true; } //returns: @@ -139,17 +139,17 @@ static gboolean scrobbler_request_token () { String tokenmsg = create_message_to_lastfm ("auth.getToken", 1, "api_key", SCROBBLER_API_KEY); - if (send_message_to_lastfm(tokenmsg) == FALSE) { + if (send_message_to_lastfm(tokenmsg) == false) { AUDDBG("Could not send token request to last.fm.\n"); - return FALSE; + return false; } - gboolean success = TRUE; + gboolean success = true; String error_code; String error_detail; - if (read_token(error_code, error_detail) == FALSE) { - success = FALSE; + if (read_token(error_code, error_detail) == false) { + success = false; if (error_code != nullptr && g_strcmp0(error_code, "8")) { //error code 8: There was an error granting the request token. Please try again later request_token = String(); @@ -161,11 +161,11 @@ static gboolean scrobbler_request_token () static gboolean update_session_key() { - gboolean result = TRUE; + gboolean result = true; String error_code; String error_detail; - if (read_session_key(error_code, error_detail) == FALSE) { + if (read_session_key(error_code, error_detail) == false) { if (error_code != nullptr && ( g_strcmp0(error_code, "4") == 0 || //invalid token g_strcmp0(error_code, "14") == 0 || //token not authorized @@ -173,9 +173,9 @@ static gboolean update_session_key() { )) { AUDDBG("error code CAUGHT: %s\n", (const char *)error_code); session_key = String(); - result = TRUE; + result = true; } else { - result= FALSE; + result= false; } } @@ -192,8 +192,8 @@ static gboolean scrobbler_request_session () String sessionmsg = create_message_to_lastfm ("auth.getSession", 2, "token", (const char *) request_token, "api_key", SCROBBLER_API_KEY); - if (send_message_to_lastfm(sessionmsg) == FALSE) - return FALSE; + if (send_message_to_lastfm(sessionmsg) == false) + return false; //the token can only be sent once request_token = String(); @@ -209,8 +209,8 @@ static gboolean scrobbler_request_session () static gboolean scrobbler_test_connection() { if (!session_key || !session_key[0]) { - scrobbling_enabled = FALSE; - return TRUE; + scrobbling_enabled = false; + return true; } String testmsg = create_message_to_lastfm ("user.getRecommendedArtists", 3, @@ -219,19 +219,19 @@ static gboolean scrobbler_test_connection() { gboolean success = send_message_to_lastfm(testmsg); - if (success == FALSE) { + if (success == false) { AUDDBG("Network problems. Will not scrobble any tracks.\n"); - scrobbling_enabled = FALSE; + scrobbling_enabled = false; if (permission_check_requested) { perm_result = PERMISSION_NONET; } - return FALSE; + return false; } String error_code; String error_detail; - if (read_authentication_test_result(error_code, error_detail) == FALSE) { + if (read_authentication_test_result(error_code, error_detail) == false) { AUDDBG("Error code: %s. Detail: %s.\n", (const char *)error_code, (const char *)error_detail); if (error_code != nullptr && ( @@ -240,16 +240,16 @@ static gboolean scrobbler_test_connection() { )) { session_key = String(); aud_set_str("scrobbler", "session_key", ""); - scrobbling_enabled = FALSE; + scrobbling_enabled = false; } else { //network problem. - scrobbling_enabled = FALSE; + scrobbling_enabled = false; AUDDBG("Connection NOT OK. Scrobbling disabled\n"); - success = FALSE; + success = false; } } else { //THIS IS THE ONLY PLACE WHERE SCROBBLING IS SET TO ENABLED IN RUN-TIME - scrobbling_enabled = TRUE; + scrobbling_enabled = true; AUDDBG("Connection OK. Scrobbling enabled.\n"); } @@ -261,28 +261,28 @@ gboolean scrobbler_communication_init() { CURLcode curl_requests_result = curl_global_init(CURL_GLOBAL_DEFAULT); if (curl_requests_result != CURLE_OK) { AUDDBG("Could not initialize libCURL: %s.\n", curl_easy_strerror(curl_requests_result)); - return FALSE; + return false; } curlHandle = curl_easy_init(); if (curlHandle == nullptr) { AUDDBG("Could not initialize libCURL.\n"); - return FALSE; + return false; } curl_requests_result = curl_easy_setopt(curlHandle, CURLOPT_URL, SCROBBLER_URL); if (curl_requests_result != CURLE_OK) { AUDDBG("Could not define scrobbler destination URL: %s.\n", curl_easy_strerror(curl_requests_result)); - return FALSE; + return false; } curl_requests_result = curl_easy_setopt(curlHandle, CURLOPT_WRITEFUNCTION, result_callback); if (curl_requests_result != CURLE_OK) { AUDDBG("Could not register scrobbler callback function: %s.\n", curl_easy_strerror(curl_requests_result)); - return FALSE; + return false; } - return TRUE; + return true; } static void set_timestamp_to_current(char **line) { @@ -405,23 +405,23 @@ static void scrobble_cached_queue() { "timestamp", line[6], "api_key", SCROBBLER_API_KEY, "sk", (const char *) session_key); - if (send_message_to_lastfm(scrobblemsg) == TRUE) { + if (send_message_to_lastfm(scrobblemsg) == true) { String error_code; String error_detail; - gboolean ignored = FALSE; + gboolean ignored = false; String ignored_code; - if (read_scrobble_result(error_code, error_detail, &ignored, ignored_code) == TRUE) { + if (read_scrobble_result(error_code, error_detail, &ignored, ignored_code) == true) { AUDDBG("SCROBBLE OK. Error code: %s. Error detail: %s\n", (const char *)error_code, (const char *)error_detail); AUDDBG("SCROBBLE OK. ignored: %i.\n", ignored); AUDDBG("SCROBBLE OK. ignored code: %s.\n", (const char *)ignored_code); - if (ignored == TRUE && g_strcmp0(ignored_code, "3") == 0) { //3: Timestamp was too old + if (ignored == true && g_strcmp0(ignored_code, "3") == 0) { //3: Timestamp was too old AUDDBG("SCROBBLE IGNORED!!! %i, detail: %s\n", ignored, (const char *)ignored_code); save_line_to_remove(&lines_to_retry, i); - } else if (ignored == TRUE && g_strcmp0(ignored_code, "") == 0) { //5: Daily scrobble limit reached + } else if (ignored == true && g_strcmp0(ignored_code, "") == 0) { //5: Daily scrobble limit reached //TODO: a track might not be scrobbled due to "daily scrobble limit exeeded". //This message comes on the ignoredMessage attribute, inside the XML of the response. //We are not dealing with this case currently and are losing that scrobble. @@ -446,7 +446,7 @@ static void scrobble_cached_queue() { } else if (g_strcmp0(error_code, "9") == 0) { //Bad Session. Reauth. - scrobbling_enabled = FALSE; + scrobbling_enabled = false; session_key = String(); aud_set_str("scrobbler", "session_key", ""); } @@ -457,7 +457,7 @@ static void scrobble_cached_queue() { } else { AUDDBG("Could not scrobble a track on the queue. Network problem?\n"); //scrobble to be retried - scrobbling_enabled = FALSE; + scrobbling_enabled = false; } //TODO: Avoid spamming last.fm --- It's not as simple as just adding a wait here: @@ -492,7 +492,7 @@ static void send_now_playing() { String error_code; String error_detail; - gboolean ignored = FALSE; + gboolean ignored = false; String ignored_code; /* * now_playing_track can be set to something else while we this method is @@ -522,10 +522,10 @@ static void send_now_playing() { gboolean success = send_message_to_lastfm(playingmsg); - if (success == FALSE) { + if (success == false) { AUDDBG("Network problems. Could not send \"now playing\" to last.fm\n"); - scrobbling_enabled = FALSE; - } else if (read_scrobble_result(error_code, error_detail, &ignored, ignored_code) == TRUE) { + scrobbling_enabled = false; + } else if (read_scrobble_result(error_code, error_detail, &ignored, ignored_code) == true) { //see scrobble_cached_queue() AUDDBG("NOW PLAYING OK.\n"); } else { @@ -536,7 +536,7 @@ static void send_now_playing() { if (g_strcmp0(error_code, "9") == 0) { //Bad Session. Reauth. //We don't really care about any other errors. - scrobbling_enabled = FALSE; + scrobbling_enabled = false; session_key = String(); aud_set_str("scrobbler", "session_key", ""); } @@ -552,28 +552,28 @@ static void treat_permission_check_request() { perm_result = PERMISSION_DENIED; if (!request_token || !request_token[0]) { - if (scrobbler_request_token() == FALSE || !request_token || !request_token[0]) { + if (scrobbler_request_token() == false || !request_token || !request_token[0]) { perm_result = PERMISSION_NONET; } //else PERMISSION_DENIED - } else if (scrobbler_request_session() == FALSE) { + } else if (scrobbler_request_session() == false) { perm_result = PERMISSION_NONET; } else if (!session_key || !session_key[0]) { //This means we had a token, a session was requested now, //but the token was not accepted or expired. //Ask for a new token now. - if (scrobbler_request_token() == FALSE || !request_token || !request_token[0]) { + if (scrobbler_request_token() == false || !request_token || !request_token[0]) { perm_result = PERMISSION_NONET; } //else PERMISSION_DENIED } } if (session_key && session_key[0]) { - if (scrobbler_test_connection() == FALSE) { + if (scrobbler_test_connection() == false) { perm_result = PERMISSION_NONET; if (!session_key || !session_key[0]) { - if (scrobbler_request_token() != FALSE && request_token && request_token[0]) { + if (scrobbler_request_token() != false && request_token && request_token[0]) { perm_result = PERMISSION_DENIED; } //else PERMISSION_NONET } @@ -590,7 +590,7 @@ static void treat_permission_check_request() { * c) the user fiddled with the audacious config file and * the key is now invalid */ - if (scrobbler_request_token() != FALSE && request_token && request_token[0]) { + if (scrobbler_request_token() != false && request_token && request_token[0]) { perm_result = PERMISSION_DENIED; } else { perm_result = PERMISSION_NONET; @@ -610,7 +610,7 @@ static gboolean treat_migrate_config() { String password = aud_get_str("audioscrobbler","password"); String username = aud_get_str("audioscrobbler","username"); if (!password[0] || !username[0]) - return FALSE; + return false; char *checksumThis = g_strdup_printf("%s%s", (const char *)username, (const char *)password); char *authToken = g_compute_checksum_for_string(G_CHECKSUM_MD5, checksumThis, -1); @@ -622,11 +622,11 @@ static gboolean treat_migrate_config() { g_free(checksumThis); g_free(authToken); - if (send_message_to_lastfm(sessionmsg) == FALSE) - return FALSE; + if (send_message_to_lastfm(sessionmsg) == false) + return false; if (!update_session_key()) - return FALSE; + return false; return (session_key && session_key[0]); } @@ -638,26 +638,26 @@ void * scrobbling_thread (void * input_data) { while (scrobbler_running) { if (migrate_config_requested) { - if (treat_migrate_config() == FALSE) { + if (treat_migrate_config() == false) { aud_ui_show_error(_("Audacious is now using an improved version of the Last.fm Scrobbler.\nPlease check the Preferences for the Scrobbler plugin.")); } aud_set_str("scrobbler", "migrated", "true"); - migrate_config_requested = FALSE; + migrate_config_requested = false; } else if (permission_check_requested) { treat_permission_check_request(); - permission_check_requested = FALSE; + permission_check_requested = false; } else if (invalidate_session_requested) { session_key = String(); aud_set_str("scrobbler", "session_key", ""); - invalidate_session_requested = FALSE; + invalidate_session_requested = false; } else if (now_playing_requested) { if (scrobbling_enabled) { send_now_playing(); } - now_playing_requested = FALSE; + now_playing_requested = false; } else { if (scrobbling_enabled) { @@ -675,7 +675,7 @@ void * scrobbling_thread (void * input_data) { //if submitting the cache failed due to network problems pthread_mutex_unlock(&communication_mutex); - if (scrobbler_test_connection() == FALSE || !scrobbling_enabled) { + if (scrobbler_test_connection() == false || !scrobbling_enabled) { struct timeval curtime; struct timespec timeout; pthread_mutex_lock(&communication_mutex); @@ -697,7 +697,7 @@ void * scrobbling_thread (void * input_data) { curl_easy_cleanup(curlHandle); curlHandle = nullptr; - scrobbling_enabled = TRUE; + scrobbling_enabled = true; return nullptr; } diff --git a/src/scrobbler2/scrobbler_xml_parsing.cc b/src/scrobbler2/scrobbler_xml_parsing.cc index b1ea05b..f555079 100644 --- a/src/scrobbler2/scrobbler_xml_parsing.cc +++ b/src/scrobbler2/scrobbler_xml_parsing.cc @@ -14,7 +14,7 @@ static gboolean prepare_data () { received_data_size = 0; if (doc == nullptr) { AUDDBG("Document not parsed successfully.\n"); - return FALSE; + return false; } context = xmlXPathNewContext(doc); @@ -22,9 +22,9 @@ static gboolean prepare_data () { AUDDBG("Error in xmlXPathNewContext\n"); xmlFreeDoc(doc); doc = nullptr; - return FALSE; + return false; } - return TRUE; + return true; } static void clean_data() { @@ -144,13 +144,13 @@ static String check_status (String &error_code, String &error_detail) { gboolean read_scrobble_result(String &error_code, String &error_detail, gboolean *ignored, String &ignored_code) { - *ignored = FALSE; + *ignored = false; - gboolean result = TRUE; + gboolean result = true; if (!prepare_data()) { AUDDBG("Could not read received data from last.fm. What's up?\n"); - return FALSE; + return false; } String status = check_status(error_code, error_detail); @@ -158,13 +158,13 @@ gboolean read_scrobble_result(String &error_code, String &error_detail, if (!status) { AUDDBG("Status was nullptr. Invalid API answer.\n"); clean_data(); - return FALSE; + return false; } if (!strcmp(status, "failed")) { AUDDBG("Error code: %s. Detail: %s.\n", (const char *)error_code, (const char *)error_detail); - result = FALSE; + result = false; } else { //TODO: We are assuming that only one track is scrobbled per request! This will have to be @@ -174,7 +174,7 @@ gboolean read_scrobble_result(String &error_code, String &error_detail, if (ignored_scrobble && strcmp(ignored_scrobble, "0")) { //The track was ignored //TODO: this assumes ignored_scrobble == 1!!! - *ignored = TRUE; + *ignored = true; ignored_code = get_attribute_value("/lfm/scrobbles/scrobble/ignoredMessage[@code]", "code"); } @@ -189,11 +189,11 @@ gboolean read_scrobble_result(String &error_code, String &error_detail, //FALSE if there was an error with the connection gboolean read_authentication_test_result (String &error_code, String &error_detail) { - gboolean result = TRUE; + gboolean result = true; if (!prepare_data()) { AUDDBG("Could not read received data from last.fm. What's up?\n"); - return FALSE; + return false; } String status = check_status(error_code, error_detail); @@ -201,17 +201,17 @@ gboolean read_authentication_test_result (String &error_code, String &error_deta if (!status) { AUDDBG("Status was nullptr. Invalid API answer.\n"); clean_data(); - return FALSE; + return false; } if (!strcmp(status, "failed")) { - result = FALSE; + result = false; } else { username = get_attribute_value("/lfm/recommendations[@user]", "user"); if (!username) { AUDDBG("last.fm not answering according to the API.\n"); - result = FALSE; + result = false; } } @@ -223,11 +223,11 @@ gboolean read_authentication_test_result (String &error_code, String &error_deta gboolean read_token (String &error_code, String &error_detail) { - gboolean result = TRUE; + gboolean result = true; if (!prepare_data()) { AUDDBG("Could not read received data from last.fm. What's up?\n"); - return FALSE; + return false; } String status = check_status(error_code, error_detail); @@ -235,20 +235,20 @@ gboolean read_token (String &error_code, String &error_detail) { if (!status) { AUDDBG("Status was nullptr. Invalid API answer.\n"); clean_data(); - return FALSE; + return false; } if (!strcmp(status, "failed")) { AUDDBG("Error code: %s. Detail: %s.\n", (const char *)error_code, (const char *)error_detail); - result = FALSE; + result = false; } else { request_token = get_node_string("/lfm/token"); if (!request_token || !request_token[0]) { AUDDBG("Could not read the received token. Something's wrong with the API?\n"); - result = FALSE; + result = false; } else { AUDDBG("This is the token: %s.\nNice? Nice.\n", (const char *)request_token); @@ -263,11 +263,11 @@ gboolean read_token (String &error_code, String &error_detail) { gboolean read_session_key(String &error_code, String &error_detail) { - gboolean result = TRUE; + gboolean result = true; if (!prepare_data()) { AUDDBG("Could not read received data from last.fm. What's up?\n"); - return FALSE; + return false; } String status = check_status(error_code, error_detail); @@ -275,20 +275,20 @@ gboolean read_session_key(String &error_code, String &error_detail) { if (!status) { AUDDBG("Status was nullptr or empty. Invalid API answer.\n"); clean_data(); - return FALSE; + return false; } if (!strcmp(status, "failed")) { AUDDBG("Error code: %s. Detail: %s.\n", (const char *)error_code, (const char *)error_detail); - result = FALSE; + result = false; } else { session_key = get_node_string("/lfm/session/key"); if (!session_key || !session_key[0]) { AUDDBG("Could not read the received session key. Something's wrong with the API?\n"); - result = FALSE; + result = false; } else { AUDDBG("This is the session key: %s.\n", (const char *)session_key); } diff --git a/src/search-tool-qt/Makefile b/src/search-tool-qt/Makefile new file mode 100644 index 0000000..a2dc91d --- /dev/null +++ b/src/search-tool-qt/Makefile @@ -0,0 +1,13 @@ +PLUGIN = search-tool-qt${PLUGIN_SUFFIX} + +SRCS = search-tool-qt.cc + +include ../../buildsys.mk +include ../../extra.mk + +plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR} + +LD = ${CXX} +CPPFLAGS += -I../.. ${GLIB_CFLAGS} ${QT_CFLAGS} +CFLAGS += ${PLUGIN_CFLAGS} +LIBS += ${GLIB_LIBS} ${QT_LIBS} -laudqt diff --git a/src/search-tool-qt/search-tool-qt.cc b/src/search-tool-qt/search-tool-qt.cc new file mode 100644 index 0000000..7a1f51b --- /dev/null +++ b/src/search-tool-qt/search-tool-qt.cc @@ -0,0 +1,769 @@ +/* + * search-tool-qt.cc + * Copyright 2011-2015 John Lindgren + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions, and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions, and the following disclaimer in the documentation + * provided with the distribution. + * + * This software is provided "as is" and without any warranty, express or + * implied. In no event shall the authors be liable for any damages arising from + * the use of this software. + */ + +#include <string.h> +#include <glib.h> + +#include <QAbstractListModel> +#include <QBoxLayout> +#include <QContextMenuEvent> +#include <QIcon> +#include <QLabel> +#include <QLineEdit> +#include <QMenu> +#include <QPushButton> +#include <QTreeView> + +#define AUD_PLUGIN_QT_ONLY +#include <libaudcore/audstrings.h> +#include <libaudcore/hook.h> +#include <libaudcore/i18n.h> +#include <libaudcore/playlist.h> +#include <libaudcore/plugin.h> +#include <libaudcore/mainloop.h> +#include <libaudcore/multihash.h> +#include <libaudcore/runtime.h> +#include <libaudqt/libaudqt.h> +#include <libaudqt/menu.h> + +#define MAX_RESULTS 20 +#define SEARCH_DELAY 300 + +class SearchToolQt : public GeneralPlugin +{ +public: + static constexpr PluginInfo info = { + N_("Search Tool"), + PACKAGE + }; + + constexpr SearchToolQt () : GeneralPlugin (info, false) {} + + void * get_qt_widget (); +}; + +EXPORT SearchToolQt aud_plugin_instance; + +enum class SearchField { + Genre, + Artist, + Album, + Title, + count +}; + +struct Key +{ + SearchField field; + String name; + + bool operator== (const Key & b) const + { return field == b.field && name == b.name; } + unsigned hash () const + { return (unsigned) field + name.hash (); } +}; + +struct Item +{ + SearchField field; + String name, folded; + Item * parent; + SimpleHash<Key, Item> children; + Index<int> matches; + + Item (SearchField field, const String & name, Item * parent) : + field (field), + name (name), + folded (str_tolower_utf8 (name)), + parent (parent) {} + + Item (Item &&) = default; + Item & operator= (Item &&) = default; +}; + +struct SearchState { + Index<const Item *> items; + int mask; +}; + +class ResultsModel : public QAbstractListModel +{ +public: + void update (); + +protected: + int rowCount (const QModelIndex & parent) const { return m_rows; } + int columnCount (const QModelIndex & parent) const { return 1; } + + QVariant data (const QModelIndex & index, int role) const; + +private: + int m_rows = 0; +}; + +class ResultsView : public QTreeView +{ +protected: + void contextMenuEvent (QContextMenuEvent * event); +}; + +static StringBuf create_item_label (int row); + +static int playlist_id; +static Index<String> search_terms; + +/* Note: added_table is accessed by multiple threads. + * When adding = true, it may only be accessed by the playlist add thread. + * When adding = false, it may only be accessed by the UI thread. + * adding may only be set by the UI thread while holding adding_lock. */ +static TinyLock adding_lock; +static bool adding = false; +static SimpleHash<String, bool> added_table; + +static SimpleHash<Key, Item> database; +static bool database_valid; +static Index<const Item *> items; +static int hidden_items; + +static QueuedFunc search_timer; +static bool search_pending; + +static ResultsModel model; +static QLabel * help_label, * wait_label, * stats_label; +static QTreeView * results_list; +static QMenu * menu; + +void ResultsModel::update () +{ + int rows = items.len (); + int keep = aud::min (rows, m_rows); + + if (rows < m_rows) + { + beginRemoveRows (QModelIndex (), rows, m_rows - 1); + m_rows = rows; + endRemoveRows (); + } + else if (rows > m_rows) + { + beginInsertRows (QModelIndex (), m_rows, rows - 1); + m_rows = rows; + endInsertRows (); + } + + if (keep > 0) + { + auto topLeft = createIndex (0, 0); + auto bottomRight = createIndex (keep - 1, 0); + emit dataChanged (topLeft, bottomRight); + } +} + +QVariant ResultsModel::data (const QModelIndex & index, int role) const +{ + if (role == Qt::DisplayRole) + return QString ((const char *) create_item_label (index.row ())); + else + return QVariant (); +} + +static void find_playlist () +{ + playlist_id = -1; + + for (int p = 0; playlist_id < 0 && p < aud_playlist_count (); p ++) + { + String title = aud_playlist_get_title (p); + if (! strcmp (title, _("Library"))) + playlist_id = aud_playlist_get_unique_id (p); + } +} + +static int create_playlist () +{ + int list = aud_playlist_get_blank (); + aud_playlist_set_title (list, _("Library")); + aud_playlist_set_active (list); + playlist_id = aud_playlist_get_unique_id (list); + return list; +} + +static int get_playlist (bool require_added, bool require_scanned) +{ + if (playlist_id < 0) + return -1; + + int list = aud_playlist_by_unique_id (playlist_id); + + if (list < 0) + { + playlist_id = -1; + return -1; + } + + if (require_added && aud_playlist_add_in_progress (list)) + return -1; + if (require_scanned && aud_playlist_scan_in_progress (list)) + return -1; + + return list; +} + +static String get_path () +{ + String path1 = aud_get_str ("search-tool", "path"); + if (g_file_test (path1, G_FILE_TEST_EXISTS)) + return path1; + + StringBuf path2 = filename_build ({g_get_home_dir (), "Music"}); + if (g_file_test (path2, G_FILE_TEST_EXISTS)) + return String (path2); + + return String (g_get_home_dir ()); +} + +static void destroy_database () +{ + items.clear (); + hidden_items = 0; + database.clear (); + database_valid = false; +} + +static void create_database (int list) +{ + destroy_database (); + + int entries = aud_playlist_entry_count (list); + + for (int e = 0; e < entries; e ++) + { + Tuple tuple = aud_playlist_entry_get_tuple (list, e, Playlist::Nothing); + + aud::array<SearchField, String> fields; + fields[SearchField::Genre] = tuple.get_str (Tuple::Genre); + fields[SearchField::Artist] = tuple.get_str (Tuple::Artist); + fields[SearchField::Album] = tuple.get_str (Tuple::Album); + fields[SearchField::Title] = tuple.get_str (Tuple::Title); + + Item * parent = nullptr; + SimpleHash<Key, Item> * hash = & database; + + for (auto f : aud::range<SearchField> ()) + { + if (fields[f]) + { + Key key = {f, fields[f]}; + Item * item = hash->lookup (key); + + if (! item) + item = hash->add (key, Item (f, fields[f], parent)); + + item->matches.append (e); + + /* genre is outside the normal hierarchy */ + if (f != SearchField::Genre) + { + parent = item; + hash = & item->children; + } + } + } + } + + database_valid = true; +} + +static void search_cb (const Key & key, Item & item, void * _state) +{ + SearchState * state = (SearchState *) _state; + + int oldmask = state->mask; + int count = search_terms.len (); + + for (int t = 0, bit = 1; t < count; t ++, bit <<= 1) + { + if (! (state->mask & bit)) + continue; /* skip term if it is already found */ + + if (strstr (item.folded, search_terms[t])) + state->mask &= ~bit; /* we found it */ + else if (! item.children.n_items ()) + break; /* quit early if there are no children to search */ + } + + /* adding an item with exactly one child is redundant, so avoid it */ + if (! state->mask && item.children.n_items () != 1) + state->items.append (& item); + + item.children.iterate (search_cb, state); + + state->mask = oldmask; +} + +static int item_compare (const Item * const & a, const Item * const & b, void *) +{ + if (a->field < b->field) + return -1; + if (a->field > b->field) + return 1; + + int val = str_compare (a->name, b->name); + if (val) + return val; + + if (a->parent) + return b->parent ? item_compare (a->parent, b->parent, nullptr) : 1; + else + return b->parent ? -1 : 0; +} + +static int item_compare_pass1 (const Item * const & a, const Item * const & b, void *) +{ + if (a->matches.len () > b->matches.len ()) + return -1; + if (a->matches.len () < b->matches.len ()) + return 1; + + return item_compare (a, b, nullptr); +} + +static void do_search () +{ + items.clear (); + hidden_items = 0; + + if (! database_valid) + return; + + SearchState state; + + /* effectively limits number of search terms to 32 */ + state.mask = (1 << search_terms.len ()) - 1; + + database.iterate (search_cb, & state); + + items = std::move (state.items); + + /* first sort by number of songs per item */ + items.sort (item_compare_pass1, nullptr); + + /* limit to items with most songs */ + if (items.len () > MAX_RESULTS) + { + hidden_items = items.len () - MAX_RESULTS; + items.remove (MAX_RESULTS, -1); + } + + /* sort by item type, then item name */ + items.sort (item_compare, nullptr); +} + +static bool filter_cb (const char * filename, void * unused) +{ + tiny_lock (& adding_lock); + bool add = adding && ! added_table.lookup (String (filename)); + tiny_unlock (& adding_lock); + return add; +} + +static void begin_add (const char * path) +{ + if (adding) + return; + + int list = get_playlist (false, false); + + if (list < 0) + list = create_playlist (); + + aud_set_str ("search-tool", "path", path); + + StringBuf uri = filename_to_uri (path); + g_return_if_fail (uri); + + if (! g_str_has_suffix (uri, "/")) + uri.insert (-1, "/"); + + added_table.clear (); + + int entries = aud_playlist_entry_count (list); + + for (int entry = 0; entry < entries; entry ++) + { + String filename = aud_playlist_entry_get_filename (list, entry); + + if (g_str_has_prefix (filename, uri) && ! added_table.lookup (filename)) + { + aud_playlist_entry_set_selected (list, entry, false); + added_table.add (filename, true); + } + else + aud_playlist_entry_set_selected (list, entry, true); + } + + aud_playlist_delete_selected (list); + aud_playlist_remove_failed (list); + + tiny_lock (& adding_lock); + adding = true; + tiny_unlock (& adding_lock); + + Index<PlaylistAddItem> add; + add.append (String (uri)); + aud_playlist_entry_insert_filtered (list, -1, std::move (add), filter_cb, nullptr, false); +} + +static void show_hide_widgets () +{ + if (playlist_id < 0) + { + wait_label->hide (); + results_list->hide (); + stats_label->hide (); + help_label->show (); + } + else + { + help_label->hide (); + + if (database_valid) + { + wait_label->hide (); + results_list->show (); + stats_label->show (); + } + else + { + results_list->hide (); + stats_label->hide (); + wait_label->show (); + } + } +} + +static void search_timeout (void * = nullptr) +{ + do_search (); + + model.update (); + + if (items.len ()) + { + auto sel = results_list->selectionModel (); + sel->select (model.index (0, 0), sel->Clear | sel->SelectCurrent); + } + + int total = items.len () + hidden_items; + StringBuf stats = str_printf (dngettext (PACKAGE, "%d result", + "%d results", total), total); + + if (hidden_items) + { + stats.insert (-1, " "); + stats.combine (str_printf (dngettext (PACKAGE, "(%d hidden)", + "(%d hidden)", hidden_items), hidden_items)); + } + + stats_label->setText ((const char *) stats); + + search_timer.stop (); + search_pending = false; +} + +static void update_database () +{ + int list = get_playlist (true, true); + + if (list >= 0) + { + create_database (list); + search_timeout (); + } + else + { + destroy_database (); + model.update (); + stats_label->clear (); + } + + show_hide_widgets (); +} + +static void add_complete_cb (void * unused, void * unused2) +{ + int list = get_playlist (true, false); + if (list < 0) + return; + + if (adding) + { + tiny_lock (& adding_lock); + adding = false; + tiny_unlock (& adding_lock); + + added_table.clear (); + aud_playlist_sort_by_scheme (list, Playlist::Path); + } + + if (! database_valid && ! aud_playlist_update_pending (list)) + update_database (); +} + +static void scan_complete_cb (void * unused, void * unused2) +{ + int list = get_playlist (true, true); + if (list < 0) + return; + + if (! database_valid && ! aud_playlist_update_pending (list)) + update_database (); +} + +static void playlist_update_cb (void * data, void * unused) +{ + if (! database_valid) + update_database (); + else + { + int list = get_playlist (true, true); + if (list < 0 || aud_playlist_update_detail (list).level >= Playlist::Metadata) + update_database (); + } +} + +static void search_init () +{ + find_playlist (); + + update_database (); + + hook_associate ("playlist add complete", add_complete_cb, nullptr); + hook_associate ("playlist scan complete", scan_complete_cb, nullptr); + hook_associate ("playlist update", playlist_update_cb, nullptr); +} + +static void search_cleanup () +{ + hook_dissociate ("playlist add complete", add_complete_cb); + hook_dissociate ("playlist scan complete", scan_complete_cb); + hook_dissociate ("playlist update", playlist_update_cb); + + search_timer.stop (); + search_pending = false; + + search_terms.clear (); + items.clear (); + + tiny_lock (& adding_lock); + adding = false; + tiny_unlock (& adding_lock); + + added_table.clear (); + destroy_database (); + + delete menu; + menu = nullptr; +} + +static void do_add (bool play, bool set_title) +{ + if (search_pending) + search_timeout (); + + int list = aud_playlist_by_unique_id (playlist_id); + int n_items = items.len (); + int n_selected = 0; + + Index<PlaylistAddItem> add; + String title; + + for (auto & idx : results_list->selectionModel ()->selectedRows ()) + { + int i = idx.row (); + if (i < 0 || i >= n_items) + continue; + + const Item * item = items[i]; + + for (int entry : item->matches) + { + add.append ( + aud_playlist_entry_get_filename (list, entry), + aud_playlist_entry_get_tuple (list, entry, Playlist::Nothing) + ); + } + + n_selected ++; + if (n_selected == 1) + title = item->name; + } + + int list2 = aud_playlist_get_active (); + aud_playlist_entry_insert_batch (list2, -1, std::move (add), play); + + if (set_title && n_selected == 1) + aud_playlist_set_title (list2, title); +} + +static void action_play () +{ + int list = aud_playlist_get_temporary (); + aud_playlist_set_active (list); + + if (aud_get_bool (nullptr, "clear_playlist")) + aud_playlist_entry_delete (list, 0, aud_playlist_entry_count (list)); + else + aud_playlist_queue_delete (list, 0, aud_playlist_queue_count (list)); + + do_add (true, false); +} + +static void action_create_playlist () +{ + aud_playlist_new (); + do_add (false, true); +} + +static void action_add_to_playlist () +{ + if (aud_playlist_by_unique_id (playlist_id) != aud_playlist_get_active ()) + do_add (false, false); +} + +static StringBuf create_item_label (int row) +{ + if (row < 0 || row >= items.len ()) + return StringBuf (); + + const Item * item = items[row]; + StringBuf string = str_concat ({item->name, "\n"}); + + if (item->field != SearchField::Title) + { + string.insert (-1, " "); + string.combine (str_printf (dngettext (PACKAGE, "%d song", "%d songs", + item->matches.len ()), item->matches.len ())); + } + + if (item->field == SearchField::Genre) + { + string.insert (-1, " "); + string.insert (-1, _("of this genre")); + } + + while ((item = item->parent)) + { + string.insert (-1, " "); + string.insert (-1, (item->field == SearchField::Album) ? _("on") : _("by")); + string.insert (-1, " "); + string.insert (-1, item->name); + } + + return string; +} + +void ResultsView::contextMenuEvent (QContextMenuEvent * event) +{ + static const audqt::MenuItem items[] = { + audqt::MenuCommand ({N_("_Play"), "media-playback-start"}, action_play), + audqt::MenuCommand ({N_("_Create Playlist"), "document-new"}, action_create_playlist), + audqt::MenuCommand ({N_("_Add to Playlist"), "list-add"}, action_add_to_playlist) + }; + + if (! menu) + menu = audqt::menu_build ({items}); + + menu->popup (event->globalPos ()); +} + +void * SearchToolQt::get_qt_widget () +{ + auto widget = new QWidget; + auto vbox = new QVBoxLayout (widget); + vbox->setContentsMargins (0, 0, 0, 0); + + auto entry = new QLineEdit; + entry->setPlaceholderText (_("Search library")); + vbox->addWidget (entry); + + help_label = new QLabel (_("To import your music library into Audacious, " + "choose a folder and then click the \"refresh\" icon.")); + help_label->setAlignment (Qt::AlignCenter); + help_label->setWordWrap (true); + vbox->addWidget (help_label); + + wait_label = new QLabel (_("Please wait ...")); + wait_label->setAlignment (Qt::AlignCenter); + vbox->addWidget (wait_label); + + results_list = new ResultsView; + results_list->setHeaderHidden (true); + results_list->setIndentation (0); + results_list->setModel (& model); + results_list->setSelectionMode (QTreeView::ExtendedSelection); + vbox->addWidget (results_list); + + stats_label = new QLabel; + stats_label->setAlignment (Qt::AlignCenter); + vbox->addWidget (stats_label); + + auto hbox = new QHBoxLayout; + vbox->addLayout (hbox); + + auto chooser = new QLineEdit; + hbox->addWidget (chooser); + + auto button = new QPushButton (QIcon::fromTheme ("view-refresh"), QString ()); + button->setFlat (true); + hbox->addWidget (button); + + char * utf8 = g_filename_to_utf8 (get_path (), -1, nullptr, nullptr, nullptr); + chooser->setText (utf8); + g_free (utf8); + + search_init (); + + QObject::connect (vbox, & QObject::destroyed, search_cleanup); + QObject::connect (entry, & QLineEdit::returnPressed, action_play); + QObject::connect (results_list, & QTreeView::doubleClicked, action_play); + + QObject::connect (entry, & QLineEdit::textEdited, [] (const QString & text) + { + search_terms = str_list_to_index (str_tolower_utf8 (text.toUtf8 ()), " "); + search_timer.queue (SEARCH_DELAY, search_timeout, nullptr); + search_pending = true; + }); + + QObject::connect (button, & QPushButton::clicked, [chooser] () + { + char * path = g_filename_from_utf8 (chooser->text ().toUtf8 (), -1, + nullptr, nullptr, nullptr); + + if (path && path[0]) + { + begin_add (path); + update_database (); + } + + g_free (path); + }); + + return widget; +} diff --git a/src/search-tool/search-tool.cc b/src/search-tool/search-tool.cc index f04ed20..4f8398e 100644 --- a/src/search-tool/search-tool.cc +++ b/src/search-tool/search-tool.cc @@ -1,6 +1,6 @@ /* - * search-tool.c - * Copyright 2011-2012 John Lindgren + * search-tool.cc + * Copyright 2011-2015 John Lindgren * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -20,13 +20,16 @@ #include <string.h> #include <gtk/gtk.h> +#define AUD_PLUGIN_GLIB_ONLY #include <libaudcore/audstrings.h> #include <libaudcore/hook.h> #include <libaudcore/i18n.h> #include <libaudcore/playlist.h> #include <libaudcore/plugin.h> +#include <libaudcore/mainloop.h> #include <libaudcore/multihash.h> #include <libaudcore/runtime.h> +#include <libaudgui/libaudgui-gtk.h> #include <libaudgui/list.h> #include <libaudgui/menu.h> @@ -94,15 +97,22 @@ struct SearchState { static int playlist_id; static Index<String> search_terms; +/* Note: added_table is accessed by multiple threads. + * When adding = true, it may only be accessed by the playlist add thread. + * When adding = false, it may only be accessed by the UI thread. + * adding may only be set by the UI thread while holding adding_lock. */ +static TinyLock adding_lock; +static bool adding = false; static SimpleHash<String, bool> added_table; + static SimpleHash<Key, Item> database; static bool database_valid; static Index<const Item *> items; static int hidden_items; static Index<bool> selection; -static gboolean adding; -static int search_source; +static QueuedFunc search_timer; +static bool search_pending; static GtkWidget * entry, * help_label, * wait_label, * scrolled, * results_list, * stats_label; @@ -127,7 +137,7 @@ static int create_playlist () return list; } -static int get_playlist (gboolean require_added, gboolean require_scanned) +static int get_playlist (bool require_added, bool require_scanned) { if (playlist_id < 0) return -1; @@ -148,11 +158,6 @@ static int get_playlist (gboolean require_added, gboolean require_scanned) return list; } -static void set_search_phrase (const char * phrase) -{ - search_terms = str_list_to_index (str_tolower_utf8 (phrase), " "); -} - static String get_path () { String path1 = aud_get_str ("search-tool", "path"); @@ -182,7 +187,7 @@ static void create_database (int list) for (int e = 0; e < entries; e ++) { - Tuple tuple = aud_playlist_entry_get_tuple (list, e, Playlist::Guess); + Tuple tuple = aud_playlist_entry_get_tuple (list, e, Playlist::Nothing); aud::array<SearchField, String> fields; fields[SearchField::Genre] = tuple.get_str (Tuple::Genre); @@ -310,11 +315,17 @@ static void do_search () static bool filter_cb (const char * filename, void * unused) { - return ! added_table.lookup (String (filename)); + tiny_lock (& adding_lock); + bool add = adding && ! added_table.lookup (String (filename)); + tiny_unlock (& adding_lock); + return add; } static void begin_add (const char * path) { + if (adding) + return; + int list = get_playlist (false, false); if (list < 0) @@ -348,11 +359,13 @@ static void begin_add (const char * path) aud_playlist_delete_selected (list); aud_playlist_remove_failed (list); + tiny_lock (& adding_lock); + adding = true; + tiny_unlock (& adding_lock); + Index<PlaylistAddItem> add; add.append (String (uri)); aud_playlist_entry_insert_filtered (list, -1, std::move (add), filter_cb, nullptr, false); - - adding = true; } static void show_hide_widgets () @@ -383,7 +396,7 @@ static void show_hide_widgets () } } -static int search_timeout (void * unused = nullptr) +static void search_timeout (void * = nullptr) { do_search (); @@ -403,21 +416,8 @@ static int search_timeout (void * unused = nullptr) gtk_label_set_text ((GtkLabel *) stats_label, stats); - if (search_source) - { - g_source_remove (search_source); - search_source = 0; - } - - return false; -} - -static void schedule_search () -{ - if (search_source) - g_source_remove (search_source); - - search_source = g_timeout_add (SEARCH_DELAY, search_timeout, nullptr); + search_timer.stop (); + search_pending = false; } static void update_database () @@ -447,7 +447,10 @@ static void add_complete_cb (void * unused, void * unused2) if (adding) { + tiny_lock (& adding_lock); adding = false; + tiny_unlock (& adding_lock); + added_table.clear (); aud_playlist_sort_by_scheme (list, Playlist::Path); } @@ -495,23 +498,24 @@ static void search_cleanup () hook_dissociate ("playlist scan complete", scan_complete_cb); hook_dissociate ("playlist update", playlist_update_cb); - if (search_source) - { - g_source_remove (search_source); - search_source = 0; - } + search_timer.stop (); + search_pending = false; search_terms.clear (); items.clear (); selection.clear (); + tiny_lock (& adding_lock); + adding = false; + tiny_unlock (& adding_lock); + added_table.clear (); destroy_database (); } -static void do_add (gboolean play, String & title) +static void do_add (bool play, bool set_title) { - if (search_source) + if (search_pending) search_timeout (); int list = aud_playlist_by_unique_id (playlist_id); @@ -519,6 +523,7 @@ static void do_add (gboolean play, String & title) int n_selected = 0; Index<PlaylistAddItem> add; + String title; for (int i = 0; i < n_items; i ++) { @@ -531,7 +536,7 @@ static void do_add (gboolean play, String & title) { add.append ( aud_playlist_entry_get_filename (list, entry), - aud_playlist_entry_get_tuple (list, entry, Playlist::Guess) + aud_playlist_entry_get_tuple (list, entry, Playlist::Nothing) ); } @@ -540,10 +545,11 @@ static void do_add (gboolean play, String & title) title = item->name; } - if (n_selected != 1) - title = String (); + int list2 = aud_playlist_get_active (); + aud_playlist_entry_insert_batch (list2, -1, std::move (add), play); - aud_playlist_entry_insert_batch (aud_playlist_get_active (), -1, std::move (add), play); + if (set_title && n_selected == 1) + aud_playlist_set_title (list2, title); } static void action_play () @@ -556,29 +562,19 @@ static void action_play () else aud_playlist_queue_delete (list, 0, aud_playlist_queue_count (list)); - String title; - do_add (true, title); + do_add (true, false); } static void action_create_playlist () { - aud_playlist_insert (-1); - aud_playlist_set_active (aud_playlist_count () - 1); - - String title; - do_add (false, title); - - if (title) - aud_playlist_set_title (aud_playlist_count () - 1, title); + aud_playlist_new (); + do_add (false, true); } static void action_add_to_playlist () { - if (aud_playlist_by_unique_id (playlist_id) == aud_playlist_get_active ()) - return; - - String title; - do_add (false, title); + if (aud_playlist_by_unique_id (playlist_id) != aud_playlist_get_active ()) + do_add (false, false); } static void list_get_value (void * user, int row, int column, GValue * value) @@ -662,8 +658,10 @@ static const AudguiListCallbacks list_callbacks = { static void entry_cb (GtkEntry * entry, void * unused) { - set_search_phrase (gtk_entry_get_text ((GtkEntry *) entry)); - schedule_search (); + const char * text = gtk_entry_get_text ((GtkEntry *) entry); + search_terms = str_list_to_index (str_tolower_utf8 (text), " "); + search_timer.queue (SEARCH_DELAY, search_timeout, nullptr); + search_pending = true; } static void refresh_cb (GtkButton * button, GtkWidget * chooser) @@ -677,52 +675,53 @@ static void refresh_cb (GtkButton * button, GtkWidget * chooser) void * SearchTool::get_gtk_widget () { - GtkWidget * vbox = gtk_vbox_new (FALSE, 6); + GtkWidget * vbox = gtk_vbox_new (false, 6); entry = gtk_entry_new (); gtk_entry_set_icon_from_icon_name ((GtkEntry *) entry, GTK_ENTRY_ICON_PRIMARY, "edit-find"); (void) _("Search library"); // translated string is used in GTK3 branch g_signal_connect (entry, "destroy", (GCallback) gtk_widget_destroyed, & entry); - gtk_box_pack_start ((GtkBox *) vbox, entry, FALSE, FALSE, 0); + gtk_box_pack_start ((GtkBox *) vbox, entry, false, false, 0); help_label = gtk_label_new (_("To import your music library into " "Audacious, choose a folder and then click the \"refresh\" icon.")); - gtk_widget_set_size_request (help_label, 194, -1); - gtk_label_set_line_wrap ((GtkLabel *) help_label, TRUE); + int label_width = aud::rescale (audgui_get_dpi (), 4, 7); + gtk_widget_set_size_request (help_label, label_width, -1); + gtk_label_set_line_wrap ((GtkLabel *) help_label, true); g_signal_connect (help_label, "destroy", (GCallback) gtk_widget_destroyed, & help_label); - gtk_widget_set_no_show_all (help_label, TRUE); - gtk_box_pack_start ((GtkBox *) vbox, help_label, TRUE, FALSE, 0); + gtk_widget_set_no_show_all (help_label, true); + gtk_box_pack_start ((GtkBox *) vbox, help_label, true, false, 0); wait_label = gtk_label_new (_("Please wait ...")); g_signal_connect (wait_label, "destroy", (GCallback) gtk_widget_destroyed, & wait_label); - gtk_widget_set_no_show_all (wait_label, TRUE); - gtk_box_pack_start ((GtkBox *) vbox, wait_label, TRUE, FALSE, 0); + gtk_widget_set_no_show_all (wait_label, true); + gtk_box_pack_start ((GtkBox *) vbox, wait_label, true, false, 0); scrolled = gtk_scrolled_window_new (nullptr, nullptr); g_signal_connect (scrolled, "destroy", (GCallback) gtk_widget_destroyed, & scrolled); gtk_scrolled_window_set_shadow_type ((GtkScrolledWindow *) scrolled, GTK_SHADOW_IN); gtk_scrolled_window_set_policy ((GtkScrolledWindow *) scrolled, GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); - gtk_widget_set_no_show_all (scrolled, TRUE); - gtk_box_pack_start ((GtkBox *) vbox, scrolled, TRUE, TRUE, 0); + gtk_widget_set_no_show_all (scrolled, true); + gtk_box_pack_start ((GtkBox *) vbox, scrolled, true, true, 0); results_list = audgui_list_new (& list_callbacks, nullptr, items.len ()); g_signal_connect (results_list, "destroy", (GCallback) gtk_widget_destroyed, & results_list); - gtk_tree_view_set_headers_visible ((GtkTreeView *) results_list, FALSE); + gtk_tree_view_set_headers_visible ((GtkTreeView *) results_list, false); audgui_list_add_column (results_list, nullptr, 0, G_TYPE_STRING, -1); gtk_container_add ((GtkContainer *) scrolled, results_list); stats_label = gtk_label_new (""); g_signal_connect (stats_label, "destroy", (GCallback) gtk_widget_destroyed, & stats_label); - gtk_widget_set_no_show_all (stats_label, TRUE); - gtk_box_pack_start ((GtkBox *) vbox, stats_label, FALSE, FALSE, 0); + gtk_widget_set_no_show_all (stats_label, true); + gtk_box_pack_start ((GtkBox *) vbox, stats_label, false, false, 0); - GtkWidget * hbox = gtk_hbox_new (FALSE, 6); - gtk_box_pack_end ((GtkBox *) vbox, hbox, FALSE, FALSE, 0); + GtkWidget * hbox = gtk_hbox_new (false, 6); + gtk_box_pack_end ((GtkBox *) vbox, hbox, false, false, 0); GtkWidget * chooser = gtk_file_chooser_button_new (_("Choose Folder"), GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER); - gtk_box_pack_start ((GtkBox *) hbox, chooser, TRUE, TRUE, 0); + gtk_box_pack_start ((GtkBox *) hbox, chooser, true, true, 0); gtk_file_chooser_set_filename ((GtkFileChooser *) chooser, get_path ()); @@ -730,7 +729,7 @@ void * SearchTool::get_gtk_widget () gtk_container_add ((GtkContainer *) button, gtk_image_new_from_icon_name ("view-refresh", GTK_ICON_SIZE_BUTTON)); gtk_button_set_relief ((GtkButton *) button, GTK_RELIEF_NONE); - gtk_box_pack_start ((GtkBox *) hbox, button, FALSE, FALSE, 0); + gtk_box_pack_start ((GtkBox *) hbox, button, false, false, 0); search_init (); diff --git a/src/sid/xs_config.cc b/src/sid/xs_config.cc index f910622..c902284 100644 --- a/src/sid/xs_config.cc +++ b/src/sid/xs_config.cc @@ -110,7 +110,7 @@ const PluginPreferences sid_prefs = {{widgets}}; /* Reset/initialize the configuration */ -void xs_init_configuration(void) +void xs_init_configuration() { aud_config_set_defaults("sid", defaults); diff --git a/src/sid/xs_config.h b/src/sid/xs_config.h index 6570b1c..cc86346 100644 --- a/src/sid/xs_config.h +++ b/src/sid/xs_config.h @@ -56,7 +56,7 @@ extern struct xs_cfg_t { /* Functions */ -void xs_init_configuration(void); +void xs_init_configuration(); struct PluginPreferences; extern const PluginPreferences sid_prefs; diff --git a/src/skins-data/Makefile b/src/skins-data/Makefile new file mode 100644 index 0000000..3b66833 --- /dev/null +++ b/src/skins-data/Makefile @@ -0,0 +1,124 @@ +include ../../buildsys.mk +include ../../extra.mk + +# These overrides variables in buildsys.mk and so must come after it. +PACKAGE_NAME = audacious +DATA = Skins/Classic/balance.png \ + Skins/Classic/cbuttons.png \ + Skins/Classic/eq_ex.png \ + Skins/Classic/eqmain.png \ + Skins/Classic/main.png \ + Skins/Classic/monoster.png \ + Skins/Classic/nums_ex.png \ + Skins/Classic/playpaus.png \ + Skins/Classic/pledit.png \ + Skins/Classic/pledit.txt \ + Skins/Classic/posbar.png \ + Skins/Classic/shufrep.png \ + Skins/Classic/skin-classic.hints \ + Skins/Classic/skin.hints \ + Skins/Classic/text.png \ + Skins/Classic/titlebar.png \ + Skins/Classic/viscolor.txt \ + Skins/Classic/volume.png \ + Skins/Classic1.3/balance.png \ + Skins/Classic1.3/cbuttons.png \ + Skins/Classic1.3/eq_ex.png \ + Skins/Classic1.3/eqmain.png \ + Skins/Classic1.3/main.png \ + Skins/Classic1.3/monoster.png \ + Skins/Classic1.3/nums_ex.png \ + Skins/Classic1.3/playpaus.png \ + Skins/Classic1.3/pledit.png \ + Skins/Classic1.3/pledit.txt \ + Skins/Classic1.3/posbar.png \ + Skins/Classic1.3/shufrep.png \ + Skins/Classic1.3/skin-classic.hints \ + Skins/Classic1.3/skin.hints \ + Skins/Classic1.3/text.png \ + Skins/Classic1.3/titlebar.png \ + Skins/Classic1.3/viscolor.txt \ + Skins/Classic1.3/volume.png \ + Skins/Default/cbuttons.png \ + Skins/Default/eq_ex.png \ + Skins/Default/eqmain.png \ + Skins/Default/main.png \ + Skins/Default/monoster.png \ + Skins/Default/nums_ex.png \ + Skins/Default/playpaus.png \ + Skins/Default/pledit.png \ + Skins/Default/pledit.txt \ + Skins/Default/posbar.png \ + Skins/Default/shufrep.png \ + Skins/Default/skin.hints \ + Skins/Default/text.png \ + Skins/Default/titlebar.png \ + Skins/Default/viscolor.txt \ + Skins/Default/volume.png \ + Skins/Ivory/balance.png \ + Skins/Ivory/cbuttons.png \ + Skins/Ivory/eq_ex.png \ + Skins/Ivory/eqmain.png \ + Skins/Ivory/main.png \ + Skins/Ivory/monoster.png \ + Skins/Ivory/nums_ex.png \ + Skins/Ivory/playpaus.png \ + Skins/Ivory/pledit.png \ + Skins/Ivory/pledit.txt \ + Skins/Ivory/posbar.png \ + Skins/Ivory/shufrep.png \ + Skins/Ivory/skin.hints \ + Skins/Ivory/text.png \ + Skins/Ivory/titlebar.png \ + Skins/Ivory/viscolor.txt \ + Skins/Ivory/volume.png \ + Skins/Osmosis/balance.png \ + Skins/Osmosis/cbuttons.png \ + Skins/Osmosis/eq_ex.png \ + Skins/Osmosis/eqmain.png \ + Skins/Osmosis/main.png \ + Skins/Osmosis/monoster.png \ + Skins/Osmosis/nums_ex.png \ + Skins/Osmosis/playpaus.png \ + Skins/Osmosis/pledit.png \ + Skins/Osmosis/pledit.txt \ + Skins/Osmosis/posbar.png \ + Skins/Osmosis/shufrep.png \ + Skins/Osmosis/skin.hints \ + Skins/Osmosis/text.png \ + Skins/Osmosis/titlebar.png \ + Skins/Osmosis/viscolor.txt \ + Skins/Osmosis/volume.png \ + Skins/TinyPlayer/balance.png \ + Skins/TinyPlayer/cbuttons.png \ + Skins/TinyPlayer/eq_ex.png \ + Skins/TinyPlayer/eqmain.png \ + Skins/TinyPlayer/main.png \ + Skins/TinyPlayer/monoster.png \ + Skins/TinyPlayer/nums_ex.png \ + Skins/TinyPlayer/playpaus.png \ + Skins/TinyPlayer/pledit.png \ + Skins/TinyPlayer/pledit.txt \ + Skins/TinyPlayer/posbar.png \ + Skins/TinyPlayer/shufrep.png \ + Skins/TinyPlayer/skin.hints \ + Skins/TinyPlayer/text.png \ + Skins/TinyPlayer/titlebar.png \ + Skins/TinyPlayer/viscolor.txt \ + Skins/TinyPlayer/volume.png \ + Skins/Refugee/cbuttons.png \ + Skins/Refugee/eq_ex.png \ + Skins/Refugee/eqmain.png \ + Skins/Refugee/main.png \ + Skins/Refugee/monoster.png \ + Skins/Refugee/nums_ex.png \ + Skins/Refugee/playpaus.png \ + Skins/Refugee/pledit.png \ + Skins/Refugee/pledit.txt \ + Skins/Refugee/posbar.png \ + Skins/Refugee/shufrep.png \ + Skins/Refugee/skin.hints \ + Skins/Refugee/text.png \ + Skins/Refugee/titlebar.png \ + Skins/Refugee/viscolor.txt \ + Skins/Refugee/volume.png diff --git a/src/skins/Skins/Classic/balance.png b/src/skins-data/Skins/Classic/balance.png Binary files differindex 1493934..1493934 100644 --- a/src/skins/Skins/Classic/balance.png +++ b/src/skins-data/Skins/Classic/balance.png diff --git a/src/skins/Skins/Classic/cbuttons.png b/src/skins-data/Skins/Classic/cbuttons.png Binary files differindex 40dea8c..40dea8c 100644 --- a/src/skins/Skins/Classic/cbuttons.png +++ b/src/skins-data/Skins/Classic/cbuttons.png diff --git a/src/skins/Skins/Classic/eq_ex.png b/src/skins-data/Skins/Classic/eq_ex.png Binary files differindex a693a84..a693a84 100644 --- a/src/skins/Skins/Classic/eq_ex.png +++ b/src/skins-data/Skins/Classic/eq_ex.png diff --git a/src/skins/Skins/Classic/eqmain.png b/src/skins-data/Skins/Classic/eqmain.png Binary files differindex fab90e8..fab90e8 100644 --- a/src/skins/Skins/Classic/eqmain.png +++ b/src/skins-data/Skins/Classic/eqmain.png diff --git a/src/skins/Skins/Classic/main.png b/src/skins-data/Skins/Classic/main.png Binary files differindex 25184ae..25184ae 100644 --- a/src/skins/Skins/Classic/main.png +++ b/src/skins-data/Skins/Classic/main.png diff --git a/src/skins/Skins/Classic/monoster.png b/src/skins-data/Skins/Classic/monoster.png Binary files differindex 84f0bc5..84f0bc5 100644 --- a/src/skins/Skins/Classic/monoster.png +++ b/src/skins-data/Skins/Classic/monoster.png diff --git a/src/skins/Skins/Classic/nums_ex.png b/src/skins-data/Skins/Classic/nums_ex.png Binary files differindex fd7f178..fd7f178 100644 --- a/src/skins/Skins/Classic/nums_ex.png +++ b/src/skins-data/Skins/Classic/nums_ex.png diff --git a/src/skins/Skins/Classic/playpaus.png b/src/skins-data/Skins/Classic/playpaus.png Binary files differindex bc0c0a6..bc0c0a6 100644 --- a/src/skins/Skins/Classic/playpaus.png +++ b/src/skins-data/Skins/Classic/playpaus.png diff --git a/src/skins/Skins/Classic/pledit.png b/src/skins-data/Skins/Classic/pledit.png Binary files differindex 6351be8..6351be8 100644 --- a/src/skins/Skins/Classic/pledit.png +++ b/src/skins-data/Skins/Classic/pledit.png diff --git a/src/skins/Skins/Classic/pledit.txt b/src/skins-data/Skins/Classic/pledit.txt index 7c6a658..7c6a658 100644 --- a/src/skins/Skins/Classic/pledit.txt +++ b/src/skins-data/Skins/Classic/pledit.txt diff --git a/src/skins/Skins/Classic/posbar.png b/src/skins-data/Skins/Classic/posbar.png Binary files differindex cdb3677..cdb3677 100644 --- a/src/skins/Skins/Classic/posbar.png +++ b/src/skins-data/Skins/Classic/posbar.png diff --git a/src/skins/Skins/Classic/shufrep.png b/src/skins-data/Skins/Classic/shufrep.png Binary files differindex d98aa90..d98aa90 100644 --- a/src/skins/Skins/Classic/shufrep.png +++ b/src/skins-data/Skins/Classic/shufrep.png diff --git a/src/skins/Skins/Classic/skin-classic.hints b/src/skins-data/Skins/Classic/skin-classic.hints index ac7a238..ac7a238 100644 --- a/src/skins/Skins/Classic/skin-classic.hints +++ b/src/skins-data/Skins/Classic/skin-classic.hints diff --git a/src/skins/Skins/Classic/skin.hints b/src/skins-data/Skins/Classic/skin.hints index 7c5f6eb..7c5f6eb 100644 --- a/src/skins/Skins/Classic/skin.hints +++ b/src/skins-data/Skins/Classic/skin.hints diff --git a/src/skins/Skins/Classic/text.png b/src/skins-data/Skins/Classic/text.png Binary files differindex 24ddfcf..24ddfcf 100644 --- a/src/skins/Skins/Classic/text.png +++ b/src/skins-data/Skins/Classic/text.png diff --git a/src/skins/Skins/Classic/titlebar.png b/src/skins-data/Skins/Classic/titlebar.png Binary files differindex acd0503..acd0503 100644 --- a/src/skins/Skins/Classic/titlebar.png +++ b/src/skins-data/Skins/Classic/titlebar.png diff --git a/src/skins/Skins/Classic/viscolor.txt b/src/skins-data/Skins/Classic/viscolor.txt index 5e00a68..5e00a68 100644 --- a/src/skins/Skins/Classic/viscolor.txt +++ b/src/skins-data/Skins/Classic/viscolor.txt diff --git a/src/skins/Skins/Classic/volume.png b/src/skins-data/Skins/Classic/volume.png Binary files differindex 9bf72ea..9bf72ea 100644 --- a/src/skins/Skins/Classic/volume.png +++ b/src/skins-data/Skins/Classic/volume.png diff --git a/src/skins/Skins/Classic1.3/balance.png b/src/skins-data/Skins/Classic1.3/balance.png Binary files differindex 35274ac..35274ac 100644 --- a/src/skins/Skins/Classic1.3/balance.png +++ b/src/skins-data/Skins/Classic1.3/balance.png diff --git a/src/skins/Skins/Classic1.3/cbuttons.png b/src/skins-data/Skins/Classic1.3/cbuttons.png Binary files differindex 1bf7a6e..1bf7a6e 100644 --- a/src/skins/Skins/Classic1.3/cbuttons.png +++ b/src/skins-data/Skins/Classic1.3/cbuttons.png diff --git a/src/skins/Skins/Classic1.3/eq_ex.png b/src/skins-data/Skins/Classic1.3/eq_ex.png Binary files differindex a693a84..a693a84 100644 --- a/src/skins/Skins/Classic1.3/eq_ex.png +++ b/src/skins-data/Skins/Classic1.3/eq_ex.png diff --git a/src/skins/Skins/Classic1.3/eqmain.png b/src/skins-data/Skins/Classic1.3/eqmain.png Binary files differindex fab90e8..fab90e8 100644 --- a/src/skins/Skins/Classic1.3/eqmain.png +++ b/src/skins-data/Skins/Classic1.3/eqmain.png diff --git a/src/skins/Skins/Classic1.3/main.png b/src/skins-data/Skins/Classic1.3/main.png Binary files differindex 94f7529..94f7529 100644 --- a/src/skins/Skins/Classic1.3/main.png +++ b/src/skins-data/Skins/Classic1.3/main.png diff --git a/src/skins/Skins/Classic1.3/monoster.png b/src/skins-data/Skins/Classic1.3/monoster.png Binary files differindex 84f0bc5..84f0bc5 100644 --- a/src/skins/Skins/Classic1.3/monoster.png +++ b/src/skins-data/Skins/Classic1.3/monoster.png diff --git a/src/skins/Skins/Classic1.3/nums_ex.png b/src/skins-data/Skins/Classic1.3/nums_ex.png Binary files differindex fd7f178..fd7f178 100644 --- a/src/skins/Skins/Classic1.3/nums_ex.png +++ b/src/skins-data/Skins/Classic1.3/nums_ex.png diff --git a/src/skins/Skins/Classic1.3/playpaus.png b/src/skins-data/Skins/Classic1.3/playpaus.png Binary files differindex bc0c0a6..bc0c0a6 100644 --- a/src/skins/Skins/Classic1.3/playpaus.png +++ b/src/skins-data/Skins/Classic1.3/playpaus.png diff --git a/src/skins/Skins/Classic1.3/pledit.png b/src/skins-data/Skins/Classic1.3/pledit.png Binary files differindex 6351be8..6351be8 100644 --- a/src/skins/Skins/Classic1.3/pledit.png +++ b/src/skins-data/Skins/Classic1.3/pledit.png diff --git a/src/skins/Skins/Classic1.3/pledit.txt b/src/skins-data/Skins/Classic1.3/pledit.txt index 7c6a658..7c6a658 100644 --- a/src/skins/Skins/Classic1.3/pledit.txt +++ b/src/skins-data/Skins/Classic1.3/pledit.txt diff --git a/src/skins/Skins/Classic1.3/posbar.png b/src/skins-data/Skins/Classic1.3/posbar.png Binary files differindex d6a6e48..d6a6e48 100644 --- a/src/skins/Skins/Classic1.3/posbar.png +++ b/src/skins-data/Skins/Classic1.3/posbar.png diff --git a/src/skins/Skins/Classic1.3/shufrep.png b/src/skins-data/Skins/Classic1.3/shufrep.png Binary files differindex c10ef47..c10ef47 100644 --- a/src/skins/Skins/Classic1.3/shufrep.png +++ b/src/skins-data/Skins/Classic1.3/shufrep.png diff --git a/src/skins/Skins/Classic1.3/skin-classic.hints b/src/skins-data/Skins/Classic1.3/skin-classic.hints index ac7a238..ac7a238 100644 --- a/src/skins/Skins/Classic1.3/skin-classic.hints +++ b/src/skins-data/Skins/Classic1.3/skin-classic.hints diff --git a/src/skins/Skins/Classic1.3/skin.hints b/src/skins-data/Skins/Classic1.3/skin.hints index 4b6d0ab..4b6d0ab 100644 --- a/src/skins/Skins/Classic1.3/skin.hints +++ b/src/skins-data/Skins/Classic1.3/skin.hints diff --git a/src/skins/Skins/Classic1.3/text.png b/src/skins-data/Skins/Classic1.3/text.png Binary files differindex 24ddfcf..24ddfcf 100644 --- a/src/skins/Skins/Classic1.3/text.png +++ b/src/skins-data/Skins/Classic1.3/text.png diff --git a/src/skins/Skins/Classic1.3/titlebar.png b/src/skins-data/Skins/Classic1.3/titlebar.png Binary files differindex bcc1b4a..bcc1b4a 100644 --- a/src/skins/Skins/Classic1.3/titlebar.png +++ b/src/skins-data/Skins/Classic1.3/titlebar.png diff --git a/src/skins/Skins/Classic1.3/viscolor.txt b/src/skins-data/Skins/Classic1.3/viscolor.txt index 9187515..9187515 100644 --- a/src/skins/Skins/Classic1.3/viscolor.txt +++ b/src/skins-data/Skins/Classic1.3/viscolor.txt diff --git a/src/skins/Skins/Classic1.3/volume.png b/src/skins-data/Skins/Classic1.3/volume.png Binary files differindex df98142..df98142 100644 --- a/src/skins/Skins/Classic1.3/volume.png +++ b/src/skins-data/Skins/Classic1.3/volume.png diff --git a/src/skins/Skins/Default/balance.png b/src/skins-data/Skins/Default/balance.png Binary files differindex 35274ac..35274ac 100644 --- a/src/skins/Skins/Default/balance.png +++ b/src/skins-data/Skins/Default/balance.png diff --git a/src/skins/Skins/Default/cbuttons.png b/src/skins-data/Skins/Default/cbuttons.png Binary files differindex bfd1939..bfd1939 100644 --- a/src/skins/Skins/Default/cbuttons.png +++ b/src/skins-data/Skins/Default/cbuttons.png diff --git a/src/skins/Skins/Default/eq_ex.png b/src/skins-data/Skins/Default/eq_ex.png Binary files differindex b34aaa3..b34aaa3 100644 --- a/src/skins/Skins/Default/eq_ex.png +++ b/src/skins-data/Skins/Default/eq_ex.png diff --git a/src/skins/Skins/Default/eqmain.png b/src/skins-data/Skins/Default/eqmain.png Binary files differindex 0a2d91a..0a2d91a 100644 --- a/src/skins/Skins/Default/eqmain.png +++ b/src/skins-data/Skins/Default/eqmain.png diff --git a/src/skins/Skins/Default/gtk-2.0/Arrows/arrow-down.png b/src/skins-data/Skins/Default/gtk-2.0/Arrows/arrow-down.png Binary files differindex ca0d0f1..ca0d0f1 100644 --- a/src/skins/Skins/Default/gtk-2.0/Arrows/arrow-down.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Arrows/arrow-down.png diff --git a/src/skins/Skins/Default/gtk-2.0/Arrows/arrow-insens.png b/src/skins-data/Skins/Default/gtk-2.0/Arrows/arrow-insens.png Binary files differindex d1b9d52..d1b9d52 100644 --- a/src/skins/Skins/Default/gtk-2.0/Arrows/arrow-insens.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Arrows/arrow-insens.png diff --git a/src/skins/Skins/Default/gtk-2.0/Arrows/arrow-left.png b/src/skins-data/Skins/Default/gtk-2.0/Arrows/arrow-left.png Binary files differindex 17b1d0b..17b1d0b 100644 --- a/src/skins/Skins/Default/gtk-2.0/Arrows/arrow-left.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Arrows/arrow-left.png diff --git a/src/skins/Skins/Default/gtk-2.0/Arrows/arrow-right.png b/src/skins-data/Skins/Default/gtk-2.0/Arrows/arrow-right.png Binary files differindex a3ecf9c..a3ecf9c 100644 --- a/src/skins/Skins/Default/gtk-2.0/Arrows/arrow-right.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Arrows/arrow-right.png diff --git a/src/skins/Skins/Default/gtk-2.0/Arrows/arrow-up.png b/src/skins-data/Skins/Default/gtk-2.0/Arrows/arrow-up.png Binary files differindex a39bf95..a39bf95 100644 --- a/src/skins/Skins/Default/gtk-2.0/Arrows/arrow-up.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Arrows/arrow-up.png diff --git a/src/skins/Skins/Default/gtk-2.0/Buttons/button-insensitive.png b/src/skins-data/Skins/Default/gtk-2.0/Buttons/button-insensitive.png Binary files differindex f85a530..f85a530 100644 --- a/src/skins/Skins/Default/gtk-2.0/Buttons/button-insensitive.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Buttons/button-insensitive.png diff --git a/src/skins/Skins/Default/gtk-2.0/Buttons/button-normal.png b/src/skins-data/Skins/Default/gtk-2.0/Buttons/button-normal.png Binary files differindex 716b010..716b010 100644 --- a/src/skins/Skins/Default/gtk-2.0/Buttons/button-normal.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Buttons/button-normal.png diff --git a/src/skins/Skins/Default/gtk-2.0/Buttons/button-prelight.png b/src/skins-data/Skins/Default/gtk-2.0/Buttons/button-prelight.png Binary files differindex 607c6dc..607c6dc 100644 --- a/src/skins/Skins/Default/gtk-2.0/Buttons/button-prelight.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Buttons/button-prelight.png diff --git a/src/skins/Skins/Default/gtk-2.0/Check-Radio/check1.png b/src/skins-data/Skins/Default/gtk-2.0/Check-Radio/check1.png Binary files differindex bf037e8..bf037e8 100644 --- a/src/skins/Skins/Default/gtk-2.0/Check-Radio/check1.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Check-Radio/check1.png diff --git a/src/skins/Skins/Default/gtk-2.0/Check-Radio/check2.png b/src/skins-data/Skins/Default/gtk-2.0/Check-Radio/check2.png Binary files differindex de087ff..de087ff 100644 --- a/src/skins/Skins/Default/gtk-2.0/Check-Radio/check2.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Check-Radio/check2.png diff --git a/src/skins/Skins/Default/gtk-2.0/Check-Radio/check3.png b/src/skins-data/Skins/Default/gtk-2.0/Check-Radio/check3.png Binary files differindex 4243aba..4243aba 100644 --- a/src/skins/Skins/Default/gtk-2.0/Check-Radio/check3.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Check-Radio/check3.png diff --git a/src/skins/Skins/Default/gtk-2.0/Check-Radio/check4.png b/src/skins-data/Skins/Default/gtk-2.0/Check-Radio/check4.png Binary files differindex e8e1b4a..e8e1b4a 100644 --- a/src/skins/Skins/Default/gtk-2.0/Check-Radio/check4.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Check-Radio/check4.png diff --git a/src/skins/Skins/Default/gtk-2.0/Check-Radio/check5.png b/src/skins-data/Skins/Default/gtk-2.0/Check-Radio/check5.png Binary files differindex 9070f42..9070f42 100644 --- a/src/skins/Skins/Default/gtk-2.0/Check-Radio/check5.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Check-Radio/check5.png diff --git a/src/skins/Skins/Default/gtk-2.0/Check-Radio/check6.png b/src/skins-data/Skins/Default/gtk-2.0/Check-Radio/check6.png Binary files differindex 46a6fc2..46a6fc2 100644 --- a/src/skins/Skins/Default/gtk-2.0/Check-Radio/check6.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Check-Radio/check6.png diff --git a/src/skins/Skins/Default/gtk-2.0/Check-Radio/option1.png b/src/skins-data/Skins/Default/gtk-2.0/Check-Radio/option1.png Binary files differindex a2143ee..a2143ee 100644 --- a/src/skins/Skins/Default/gtk-2.0/Check-Radio/option1.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Check-Radio/option1.png diff --git a/src/skins/Skins/Default/gtk-2.0/Check-Radio/option2.png b/src/skins-data/Skins/Default/gtk-2.0/Check-Radio/option2.png Binary files differindex be45e43..be45e43 100644 --- a/src/skins/Skins/Default/gtk-2.0/Check-Radio/option2.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Check-Radio/option2.png diff --git a/src/skins/Skins/Default/gtk-2.0/Check-Radio/option3.png b/src/skins-data/Skins/Default/gtk-2.0/Check-Radio/option3.png Binary files differindex f013f4b..f013f4b 100644 --- a/src/skins/Skins/Default/gtk-2.0/Check-Radio/option3.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Check-Radio/option3.png diff --git a/src/skins/Skins/Default/gtk-2.0/Check-Radio/option4.png b/src/skins-data/Skins/Default/gtk-2.0/Check-Radio/option4.png Binary files differindex 6199532..6199532 100644 --- a/src/skins/Skins/Default/gtk-2.0/Check-Radio/option4.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Check-Radio/option4.png diff --git a/src/skins/Skins/Default/gtk-2.0/Check-Radio/option5.png b/src/skins-data/Skins/Default/gtk-2.0/Check-Radio/option5.png Binary files differindex 3f6f795..3f6f795 100644 --- a/src/skins/Skins/Default/gtk-2.0/Check-Radio/option5.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Check-Radio/option5.png diff --git a/src/skins/Skins/Default/gtk-2.0/Check-Radio/option6.png b/src/skins-data/Skins/Default/gtk-2.0/Check-Radio/option6.png Binary files differindex 1984f79..1984f79 100644 --- a/src/skins/Skins/Default/gtk-2.0/Check-Radio/option6.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Check-Radio/option6.png diff --git a/src/skins/Skins/Default/gtk-2.0/Frame-Gap/frame-gap-end.png b/src/skins-data/Skins/Default/gtk-2.0/Frame-Gap/frame-gap-end.png Binary files differindex 5b9357f..5b9357f 100644 --- a/src/skins/Skins/Default/gtk-2.0/Frame-Gap/frame-gap-end.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Frame-Gap/frame-gap-end.png diff --git a/src/skins/Skins/Default/gtk-2.0/Frame-Gap/frame-gap-start.png b/src/skins-data/Skins/Default/gtk-2.0/Frame-Gap/frame-gap-start.png Binary files differindex d44f8db..d44f8db 100644 --- a/src/skins/Skins/Default/gtk-2.0/Frame-Gap/frame-gap-start.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Frame-Gap/frame-gap-start.png diff --git a/src/skins/Skins/Default/gtk-2.0/Frame-Gap/frame.png b/src/skins-data/Skins/Default/gtk-2.0/Frame-Gap/frame.png Binary files differindex 2f7b353..2f7b353 100644 --- a/src/skins/Skins/Default/gtk-2.0/Frame-Gap/frame.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Frame-Gap/frame.png diff --git a/src/skins/Skins/Default/gtk-2.0/Handles/handle-h.png b/src/skins-data/Skins/Default/gtk-2.0/Handles/handle-h.png Binary files differindex 4a987aa..4a987aa 100644 --- a/src/skins/Skins/Default/gtk-2.0/Handles/handle-h.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Handles/handle-h.png diff --git a/src/skins/Skins/Default/gtk-2.0/Handles/handle-v.png b/src/skins-data/Skins/Default/gtk-2.0/Handles/handle-v.png Binary files differindex 90b6f21..90b6f21 100644 --- a/src/skins/Skins/Default/gtk-2.0/Handles/handle-v.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Handles/handle-v.png diff --git a/src/skins/Skins/Default/gtk-2.0/Lines/line-h.png b/src/skins-data/Skins/Default/gtk-2.0/Lines/line-h.png Binary files differindex 5193ab0..5193ab0 100644 --- a/src/skins/Skins/Default/gtk-2.0/Lines/line-h.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Lines/line-h.png diff --git a/src/skins/Skins/Default/gtk-2.0/Lines/line-v.png b/src/skins-data/Skins/Default/gtk-2.0/Lines/line-v.png Binary files differindex 244a516..244a516 100644 --- a/src/skins/Skins/Default/gtk-2.0/Lines/line-v.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Lines/line-v.png diff --git a/src/skins/Skins/Default/gtk-2.0/ListHeaders/list_header-insens.png b/src/skins-data/Skins/Default/gtk-2.0/ListHeaders/list_header-insens.png Binary files differindex f3d417a..f3d417a 100644 --- a/src/skins/Skins/Default/gtk-2.0/ListHeaders/list_header-insens.png +++ b/src/skins-data/Skins/Default/gtk-2.0/ListHeaders/list_header-insens.png diff --git a/src/skins/Skins/Default/gtk-2.0/ListHeaders/list_header-prelight.png b/src/skins-data/Skins/Default/gtk-2.0/ListHeaders/list_header-prelight.png Binary files differindex 6fb735a..6fb735a 100644 --- a/src/skins/Skins/Default/gtk-2.0/ListHeaders/list_header-prelight.png +++ b/src/skins-data/Skins/Default/gtk-2.0/ListHeaders/list_header-prelight.png diff --git a/src/skins/Skins/Default/gtk-2.0/ListHeaders/list_header-pressed.png b/src/skins-data/Skins/Default/gtk-2.0/ListHeaders/list_header-pressed.png Binary files differindex f5358a7..f5358a7 100644 --- a/src/skins/Skins/Default/gtk-2.0/ListHeaders/list_header-pressed.png +++ b/src/skins-data/Skins/Default/gtk-2.0/ListHeaders/list_header-pressed.png diff --git a/src/skins/Skins/Default/gtk-2.0/ListHeaders/list_header.png b/src/skins-data/Skins/Default/gtk-2.0/ListHeaders/list_header.png Binary files differindex da50ee3..da50ee3 100644 --- a/src/skins/Skins/Default/gtk-2.0/ListHeaders/list_header.png +++ b/src/skins-data/Skins/Default/gtk-2.0/ListHeaders/list_header.png diff --git a/src/skins/Skins/Default/gtk-2.0/Menu-Menubar/menu.png b/src/skins-data/Skins/Default/gtk-2.0/Menu-Menubar/menu.png Binary files differindex 6a8d218..6a8d218 100644 --- a/src/skins/Skins/Default/gtk-2.0/Menu-Menubar/menu.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Menu-Menubar/menu.png diff --git a/src/skins/Skins/Default/gtk-2.0/Menu-Menubar/menubar-item-active.png b/src/skins-data/Skins/Default/gtk-2.0/Menu-Menubar/menubar-item-active.png Binary files differindex 0124412..0124412 100644 --- a/src/skins/Skins/Default/gtk-2.0/Menu-Menubar/menubar-item-active.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Menu-Menubar/menubar-item-active.png diff --git a/src/skins/Skins/Default/gtk-2.0/Menu-Menubar/menubar-item.png b/src/skins-data/Skins/Default/gtk-2.0/Menu-Menubar/menubar-item.png Binary files differindex 6287cca..6287cca 100644 --- a/src/skins/Skins/Default/gtk-2.0/Menu-Menubar/menubar-item.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Menu-Menubar/menubar-item.png diff --git a/src/skins/Skins/Default/gtk-2.0/Menu-Menubar/menubar.png b/src/skins-data/Skins/Default/gtk-2.0/Menu-Menubar/menubar.png Binary files differindex eb1ff85..eb1ff85 100644 --- a/src/skins/Skins/Default/gtk-2.0/Menu-Menubar/menubar.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Menu-Menubar/menubar.png diff --git a/src/skins/Skins/Default/gtk-2.0/Others/null.png b/src/skins-data/Skins/Default/gtk-2.0/Others/null.png Binary files differindex 7e52ab7..7e52ab7 100644 --- a/src/skins/Skins/Default/gtk-2.0/Others/null.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Others/null.png diff --git a/src/skins/Skins/Default/gtk-2.0/Others/ruler.png b/src/skins-data/Skins/Default/gtk-2.0/Others/ruler.png Binary files differindex 31aa7de..31aa7de 100644 --- a/src/skins/Skins/Default/gtk-2.0/Others/ruler.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Others/ruler.png diff --git a/src/skins/Skins/Default/gtk-2.0/Panel/panel-bg.png b/src/skins-data/Skins/Default/gtk-2.0/Panel/panel-bg.png Binary files differindex f8b3cd6..f8b3cd6 100644 --- a/src/skins/Skins/Default/gtk-2.0/Panel/panel-bg.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Panel/panel-bg.png diff --git a/src/skins/Skins/Default/gtk-2.0/ProgressBar/progressbar-horiz.png b/src/skins-data/Skins/Default/gtk-2.0/ProgressBar/progressbar-horiz.png Binary files differindex d479747..d479747 100644 --- a/src/skins/Skins/Default/gtk-2.0/ProgressBar/progressbar-horiz.png +++ b/src/skins-data/Skins/Default/gtk-2.0/ProgressBar/progressbar-horiz.png diff --git a/src/skins/Skins/Default/gtk-2.0/ProgressBar/trough-progressbar-horiz.png b/src/skins-data/Skins/Default/gtk-2.0/ProgressBar/trough-progressbar-horiz.png Binary files differindex 7c92f33..7c92f33 100644 --- a/src/skins/Skins/Default/gtk-2.0/ProgressBar/trough-progressbar-horiz.png +++ b/src/skins-data/Skins/Default/gtk-2.0/ProgressBar/trough-progressbar-horiz.png diff --git a/src/skins/Skins/Default/gtk-2.0/Range/slider-horiz-prelight.png b/src/skins-data/Skins/Default/gtk-2.0/Range/slider-horiz-prelight.png Binary files differindex 6d29b55..6d29b55 100644 --- a/src/skins/Skins/Default/gtk-2.0/Range/slider-horiz-prelight.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Range/slider-horiz-prelight.png diff --git a/src/skins/Skins/Default/gtk-2.0/Range/slider-horiz.png b/src/skins-data/Skins/Default/gtk-2.0/Range/slider-horiz.png Binary files differindex 43e81db..43e81db 100644 --- a/src/skins/Skins/Default/gtk-2.0/Range/slider-horiz.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Range/slider-horiz.png diff --git a/src/skins/Skins/Default/gtk-2.0/Range/slider-vert-prelight.png b/src/skins-data/Skins/Default/gtk-2.0/Range/slider-vert-prelight.png Binary files differindex f2c6598..f2c6598 100644 --- a/src/skins/Skins/Default/gtk-2.0/Range/slider-vert-prelight.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Range/slider-vert-prelight.png diff --git a/src/skins/Skins/Default/gtk-2.0/Range/slider-vert.png b/src/skins-data/Skins/Default/gtk-2.0/Range/slider-vert.png Binary files differindex b5e52c6..b5e52c6 100644 --- a/src/skins/Skins/Default/gtk-2.0/Range/slider-vert.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Range/slider-vert.png diff --git a/src/skins/Skins/Default/gtk-2.0/Range/trough-horizontal.png b/src/skins-data/Skins/Default/gtk-2.0/Range/trough-horizontal.png Binary files differindex df82885..df82885 100644 --- a/src/skins/Skins/Default/gtk-2.0/Range/trough-horizontal.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Range/trough-horizontal.png diff --git a/src/skins/Skins/Default/gtk-2.0/Range/trough-vertical.png b/src/skins-data/Skins/Default/gtk-2.0/Range/trough-vertical.png Binary files differindex 82b95a4..82b95a4 100644 --- a/src/skins/Skins/Default/gtk-2.0/Range/trough-vertical.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Range/trough-vertical.png diff --git a/src/skins/Skins/Default/gtk-2.0/Scrollbars/scroll-thumb-horiz-pre.png b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/scroll-thumb-horiz-pre.png Binary files differindex f7f003f..f7f003f 100644 --- a/src/skins/Skins/Default/gtk-2.0/Scrollbars/scroll-thumb-horiz-pre.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/scroll-thumb-horiz-pre.png diff --git a/src/skins/Skins/Default/gtk-2.0/Scrollbars/scroll-thumb-horiz.png b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/scroll-thumb-horiz.png Binary files differindex f32aa50..f32aa50 100644 --- a/src/skins/Skins/Default/gtk-2.0/Scrollbars/scroll-thumb-horiz.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/scroll-thumb-horiz.png diff --git a/src/skins/Skins/Default/gtk-2.0/Scrollbars/scroll-thumb-vert-pre.png b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/scroll-thumb-vert-pre.png Binary files differindex 1048ea9..1048ea9 100644 --- a/src/skins/Skins/Default/gtk-2.0/Scrollbars/scroll-thumb-vert-pre.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/scroll-thumb-vert-pre.png diff --git a/src/skins/Skins/Default/gtk-2.0/Scrollbars/scroll-thumb-vert.png b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/scroll-thumb-vert.png Binary files differindex f56f132..f56f132 100644 --- a/src/skins/Skins/Default/gtk-2.0/Scrollbars/scroll-thumb-vert.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/scroll-thumb-vert.png diff --git a/src/skins/Skins/Default/gtk-2.0/Scrollbars/slider-horiz-pre.png b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/slider-horiz-pre.png Binary files differindex c3e9b14..c3e9b14 100644 --- a/src/skins/Skins/Default/gtk-2.0/Scrollbars/slider-horiz-pre.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/slider-horiz-pre.png diff --git a/src/skins/Skins/Default/gtk-2.0/Scrollbars/slider-horiz.png b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/slider-horiz.png Binary files differindex aa2e0e5..aa2e0e5 100644 --- a/src/skins/Skins/Default/gtk-2.0/Scrollbars/slider-horiz.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/slider-horiz.png diff --git a/src/skins/Skins/Default/gtk-2.0/Scrollbars/slider-vert-pre.png b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/slider-vert-pre.png Binary files differindex 8ab8a3e..8ab8a3e 100644 --- a/src/skins/Skins/Default/gtk-2.0/Scrollbars/slider-vert-pre.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/slider-vert-pre.png diff --git a/src/skins/Skins/Default/gtk-2.0/Scrollbars/slider-vert.png b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/slider-vert.png Binary files differindex e8f972e..e8f972e 100644 --- a/src/skins/Skins/Default/gtk-2.0/Scrollbars/slider-vert.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/slider-vert.png diff --git a/src/skins/Skins/Default/gtk-2.0/Scrollbars/stepper-down-prelight.png b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/stepper-down-prelight.png Binary files differindex a1fd7c1..a1fd7c1 100644 --- a/src/skins/Skins/Default/gtk-2.0/Scrollbars/stepper-down-prelight.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/stepper-down-prelight.png diff --git a/src/skins/Skins/Default/gtk-2.0/Scrollbars/stepper-down.png b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/stepper-down.png Binary files differindex 06934e4..06934e4 100644 --- a/src/skins/Skins/Default/gtk-2.0/Scrollbars/stepper-down.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/stepper-down.png diff --git a/src/skins/Skins/Default/gtk-2.0/Scrollbars/stepper-left-prelight.png b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/stepper-left-prelight.png Binary files differindex 3878d16..3878d16 100644 --- a/src/skins/Skins/Default/gtk-2.0/Scrollbars/stepper-left-prelight.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/stepper-left-prelight.png diff --git a/src/skins/Skins/Default/gtk-2.0/Scrollbars/stepper-left.png b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/stepper-left.png Binary files differindex dd82b4b..dd82b4b 100644 --- a/src/skins/Skins/Default/gtk-2.0/Scrollbars/stepper-left.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/stepper-left.png diff --git a/src/skins/Skins/Default/gtk-2.0/Scrollbars/stepper-right-prelight.png b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/stepper-right-prelight.png Binary files differindex 31689c5..31689c5 100644 --- a/src/skins/Skins/Default/gtk-2.0/Scrollbars/stepper-right-prelight.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/stepper-right-prelight.png diff --git a/src/skins/Skins/Default/gtk-2.0/Scrollbars/stepper-right.png b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/stepper-right.png Binary files differindex eecf08e..eecf08e 100644 --- a/src/skins/Skins/Default/gtk-2.0/Scrollbars/stepper-right.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/stepper-right.png diff --git a/src/skins/Skins/Default/gtk-2.0/Scrollbars/stepper-up-prelight.png b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/stepper-up-prelight.png Binary files differindex bac8a4f..bac8a4f 100644 --- a/src/skins/Skins/Default/gtk-2.0/Scrollbars/stepper-up-prelight.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/stepper-up-prelight.png diff --git a/src/skins/Skins/Default/gtk-2.0/Scrollbars/stepper-up.png b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/stepper-up.png Binary files differindex 71898f0..71898f0 100644 --- a/src/skins/Skins/Default/gtk-2.0/Scrollbars/stepper-up.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/stepper-up.png diff --git a/src/skins/Skins/Default/gtk-2.0/Scrollbars/trough-scrollbar-horiz.png b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/trough-scrollbar-horiz.png Binary files differindex 7de09ba..7de09ba 100644 --- a/src/skins/Skins/Default/gtk-2.0/Scrollbars/trough-scrollbar-horiz.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/trough-scrollbar-horiz.png diff --git a/src/skins/Skins/Default/gtk-2.0/Scrollbars/trough-scrollbar-vert.png b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/trough-scrollbar-vert.png Binary files differindex 884c916..884c916 100644 --- a/src/skins/Skins/Default/gtk-2.0/Scrollbars/trough-scrollbar-vert.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Scrollbars/trough-scrollbar-vert.png diff --git a/src/skins/Skins/Default/gtk-2.0/Shadows/shadow-in.png b/src/skins-data/Skins/Default/gtk-2.0/Shadows/shadow-in.png Binary files differindex 0d1eda6..0d1eda6 100644 --- a/src/skins/Skins/Default/gtk-2.0/Shadows/shadow-in.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Shadows/shadow-in.png diff --git a/src/skins/Skins/Default/gtk-2.0/Shadows/shadow-out.png b/src/skins-data/Skins/Default/gtk-2.0/Shadows/shadow-out.png Binary files differindex e460df8..e460df8 100644 --- a/src/skins/Skins/Default/gtk-2.0/Shadows/shadow-out.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Shadows/shadow-out.png diff --git a/src/skins/Skins/Default/gtk-2.0/Shadows/text-.png b/src/skins-data/Skins/Default/gtk-2.0/Shadows/text-.png Binary files differindex e1c0ea6..e1c0ea6 100644 --- a/src/skins/Skins/Default/gtk-2.0/Shadows/text-.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Shadows/text-.png diff --git a/src/skins/Skins/Default/gtk-2.0/Shadows/text-entry.png b/src/skins-data/Skins/Default/gtk-2.0/Shadows/text-entry.png Binary files differindex 1dfcc21..1dfcc21 100644 --- a/src/skins/Skins/Default/gtk-2.0/Shadows/text-entry.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Shadows/text-entry.png diff --git a/src/skins/Skins/Default/gtk-2.0/Spin/spin-down-disable.png b/src/skins-data/Skins/Default/gtk-2.0/Spin/spin-down-disable.png Binary files differindex 768d6a6..768d6a6 100644 --- a/src/skins/Skins/Default/gtk-2.0/Spin/spin-down-disable.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Spin/spin-down-disable.png diff --git a/src/skins/Skins/Default/gtk-2.0/Spin/spin-down-prelight.png b/src/skins-data/Skins/Default/gtk-2.0/Spin/spin-down-prelight.png Binary files differindex e824c32..e824c32 100644 --- a/src/skins/Skins/Default/gtk-2.0/Spin/spin-down-prelight.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Spin/spin-down-prelight.png diff --git a/src/skins/Skins/Default/gtk-2.0/Spin/spin-down.png b/src/skins-data/Skins/Default/gtk-2.0/Spin/spin-down.png Binary files differindex 17344e2..17344e2 100644 --- a/src/skins/Skins/Default/gtk-2.0/Spin/spin-down.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Spin/spin-down.png diff --git a/src/skins/Skins/Default/gtk-2.0/Spin/spin-up-disable.png b/src/skins-data/Skins/Default/gtk-2.0/Spin/spin-up-disable.png Binary files differindex 365c53b..365c53b 100644 --- a/src/skins/Skins/Default/gtk-2.0/Spin/spin-up-disable.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Spin/spin-up-disable.png diff --git a/src/skins/Skins/Default/gtk-2.0/Spin/spin-up-prelight.png b/src/skins-data/Skins/Default/gtk-2.0/Spin/spin-up-prelight.png Binary files differindex e597e13..e597e13 100644 --- a/src/skins/Skins/Default/gtk-2.0/Spin/spin-up-prelight.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Spin/spin-up-prelight.png diff --git a/src/skins/Skins/Default/gtk-2.0/Spin/spin-up.png b/src/skins-data/Skins/Default/gtk-2.0/Spin/spin-up.png Binary files differindex bc3742c..bc3742c 100644 --- a/src/skins/Skins/Default/gtk-2.0/Spin/spin-up.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Spin/spin-up.png diff --git a/src/skins/Skins/Default/gtk-2.0/Tabs/gap-bottom-left.png b/src/skins-data/Skins/Default/gtk-2.0/Tabs/gap-bottom-left.png Binary files differindex 70d14e2..70d14e2 100644 --- a/src/skins/Skins/Default/gtk-2.0/Tabs/gap-bottom-left.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Tabs/gap-bottom-left.png diff --git a/src/skins/Skins/Default/gtk-2.0/Tabs/gap-bottom-right.png b/src/skins-data/Skins/Default/gtk-2.0/Tabs/gap-bottom-right.png Binary files differindex 6208f42..6208f42 100644 --- a/src/skins/Skins/Default/gtk-2.0/Tabs/gap-bottom-right.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Tabs/gap-bottom-right.png diff --git a/src/skins/Skins/Default/gtk-2.0/Tabs/gap-left-bottom.png b/src/skins-data/Skins/Default/gtk-2.0/Tabs/gap-left-bottom.png Binary files differindex d9da62c..d9da62c 100644 --- a/src/skins/Skins/Default/gtk-2.0/Tabs/gap-left-bottom.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Tabs/gap-left-bottom.png diff --git a/src/skins/Skins/Default/gtk-2.0/Tabs/gap-left-top.png b/src/skins-data/Skins/Default/gtk-2.0/Tabs/gap-left-top.png Binary files differindex 3f0ab5d..3f0ab5d 100644 --- a/src/skins/Skins/Default/gtk-2.0/Tabs/gap-left-top.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Tabs/gap-left-top.png diff --git a/src/skins/Skins/Default/gtk-2.0/Tabs/gap-right-bottom.png b/src/skins-data/Skins/Default/gtk-2.0/Tabs/gap-right-bottom.png Binary files differindex 3a31a13..3a31a13 100644 --- a/src/skins/Skins/Default/gtk-2.0/Tabs/gap-right-bottom.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Tabs/gap-right-bottom.png diff --git a/src/skins/Skins/Default/gtk-2.0/Tabs/gap-right-top.png b/src/skins-data/Skins/Default/gtk-2.0/Tabs/gap-right-top.png Binary files differindex 14c7159..14c7159 100644 --- a/src/skins/Skins/Default/gtk-2.0/Tabs/gap-right-top.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Tabs/gap-right-top.png diff --git a/src/skins/Skins/Default/gtk-2.0/Tabs/gap-top-current.png b/src/skins-data/Skins/Default/gtk-2.0/Tabs/gap-top-current.png Binary files differindex 1a17c50..1a17c50 100644 --- a/src/skins/Skins/Default/gtk-2.0/Tabs/gap-top-current.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Tabs/gap-top-current.png diff --git a/src/skins/Skins/Default/gtk-2.0/Tabs/gap-top-left.png b/src/skins-data/Skins/Default/gtk-2.0/Tabs/gap-top-left.png Binary files differindex 6c9b064..6c9b064 100644 --- a/src/skins/Skins/Default/gtk-2.0/Tabs/gap-top-left.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Tabs/gap-top-left.png diff --git a/src/skins/Skins/Default/gtk-2.0/Tabs/gap-top-right.png b/src/skins-data/Skins/Default/gtk-2.0/Tabs/gap-top-right.png Binary files differindex 00e3367..00e3367 100644 --- a/src/skins/Skins/Default/gtk-2.0/Tabs/gap-top-right.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Tabs/gap-top-right.png diff --git a/src/skins/Skins/Default/gtk-2.0/Tabs/notebook.png b/src/skins-data/Skins/Default/gtk-2.0/Tabs/notebook.png Binary files differindex f358cc3..f358cc3 100644 --- a/src/skins/Skins/Default/gtk-2.0/Tabs/notebook.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Tabs/notebook.png diff --git a/src/skins/Skins/Default/gtk-2.0/Tabs/tab-bottom-active.png b/src/skins-data/Skins/Default/gtk-2.0/Tabs/tab-bottom-active.png Binary files differindex cd42573..cd42573 100644 --- a/src/skins/Skins/Default/gtk-2.0/Tabs/tab-bottom-active.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Tabs/tab-bottom-active.png diff --git a/src/skins/Skins/Default/gtk-2.0/Tabs/tab-bottom.png b/src/skins-data/Skins/Default/gtk-2.0/Tabs/tab-bottom.png Binary files differindex a4c6e4b..a4c6e4b 100644 --- a/src/skins/Skins/Default/gtk-2.0/Tabs/tab-bottom.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Tabs/tab-bottom.png diff --git a/src/skins/Skins/Default/gtk-2.0/Tabs/tab-left-active.png b/src/skins-data/Skins/Default/gtk-2.0/Tabs/tab-left-active.png Binary files differindex 1113d28..1113d28 100644 --- a/src/skins/Skins/Default/gtk-2.0/Tabs/tab-left-active.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Tabs/tab-left-active.png diff --git a/src/skins/Skins/Default/gtk-2.0/Tabs/tab-left.png b/src/skins-data/Skins/Default/gtk-2.0/Tabs/tab-left.png Binary files differindex 32492f1..32492f1 100644 --- a/src/skins/Skins/Default/gtk-2.0/Tabs/tab-left.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Tabs/tab-left.png diff --git a/src/skins/Skins/Default/gtk-2.0/Tabs/tab-right-active.png b/src/skins-data/Skins/Default/gtk-2.0/Tabs/tab-right-active.png Binary files differindex 0dec964..0dec964 100644 --- a/src/skins/Skins/Default/gtk-2.0/Tabs/tab-right-active.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Tabs/tab-right-active.png diff --git a/src/skins/Skins/Default/gtk-2.0/Tabs/tab-right.png b/src/skins-data/Skins/Default/gtk-2.0/Tabs/tab-right.png Binary files differindex dc00d63..dc00d63 100644 --- a/src/skins/Skins/Default/gtk-2.0/Tabs/tab-right.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Tabs/tab-right.png diff --git a/src/skins/Skins/Default/gtk-2.0/Tabs/tab-top-active.png b/src/skins-data/Skins/Default/gtk-2.0/Tabs/tab-top-active.png Binary files differindex c050b0a..c050b0a 100644 --- a/src/skins/Skins/Default/gtk-2.0/Tabs/tab-top-active.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Tabs/tab-top-active.png diff --git a/src/skins/Skins/Default/gtk-2.0/Tabs/tab-top.png b/src/skins-data/Skins/Default/gtk-2.0/Tabs/tab-top.png Binary files differindex ea0d190..ea0d190 100644 --- a/src/skins/Skins/Default/gtk-2.0/Tabs/tab-top.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Tabs/tab-top.png diff --git a/src/skins/Skins/Default/gtk-2.0/Toolbar/toolbar.png b/src/skins-data/Skins/Default/gtk-2.0/Toolbar/toolbar.png Binary files differindex b49df8a..b49df8a 100644 --- a/src/skins/Skins/Default/gtk-2.0/Toolbar/toolbar.png +++ b/src/skins-data/Skins/Default/gtk-2.0/Toolbar/toolbar.png diff --git a/src/skins/Skins/Default/gtk-2.0/gtkrc b/src/skins-data/Skins/Default/gtk-2.0/gtkrc index 48652a1..48652a1 100644 --- a/src/skins/Skins/Default/gtk-2.0/gtkrc +++ b/src/skins-data/Skins/Default/gtk-2.0/gtkrc diff --git a/src/skins/Skins/Default/gtk-2.0/panel.rc b/src/skins-data/Skins/Default/gtk-2.0/panel.rc index f634eca..f634eca 100644 --- a/src/skins/Skins/Default/gtk-2.0/panel.rc +++ b/src/skins-data/Skins/Default/gtk-2.0/panel.rc diff --git a/src/skins/Skins/Default/main.png b/src/skins-data/Skins/Default/main.png Binary files differindex fa1bec3..fa1bec3 100644 --- a/src/skins/Skins/Default/main.png +++ b/src/skins-data/Skins/Default/main.png diff --git a/src/skins/Skins/Default/monoster.png b/src/skins-data/Skins/Default/monoster.png Binary files differindex dab972a..dab972a 100644 --- a/src/skins/Skins/Default/monoster.png +++ b/src/skins-data/Skins/Default/monoster.png diff --git a/src/skins/Skins/Default/nums_ex.png b/src/skins-data/Skins/Default/nums_ex.png Binary files differindex 53adeeb..53adeeb 100644 --- a/src/skins/Skins/Default/nums_ex.png +++ b/src/skins-data/Skins/Default/nums_ex.png diff --git a/src/skins/Skins/Default/playpaus.png b/src/skins-data/Skins/Default/playpaus.png Binary files differindex 3e1c564..3e1c564 100644 --- a/src/skins/Skins/Default/playpaus.png +++ b/src/skins-data/Skins/Default/playpaus.png diff --git a/src/skins/Skins/Default/pledit.png b/src/skins-data/Skins/Default/pledit.png Binary files differindex 4d4a51a..4d4a51a 100644 --- a/src/skins/Skins/Default/pledit.png +++ b/src/skins-data/Skins/Default/pledit.png diff --git a/src/skins/Skins/Default/pledit.txt b/src/skins-data/Skins/Default/pledit.txt index a7bbdbe..a7bbdbe 100644 --- a/src/skins/Skins/Default/pledit.txt +++ b/src/skins-data/Skins/Default/pledit.txt diff --git a/src/skins/Skins/Default/posbar.png b/src/skins-data/Skins/Default/posbar.png Binary files differindex f229e05..f229e05 100644 --- a/src/skins/Skins/Default/posbar.png +++ b/src/skins-data/Skins/Default/posbar.png diff --git a/src/skins/Skins/Default/shufrep.png b/src/skins-data/Skins/Default/shufrep.png Binary files differindex d7f6d56..d7f6d56 100644 --- a/src/skins/Skins/Default/shufrep.png +++ b/src/skins-data/Skins/Default/shufrep.png diff --git a/src/skins/Skins/Default/skin-classic.hints b/src/skins-data/Skins/Default/skin-classic.hints index ac7a238..ac7a238 100644 --- a/src/skins/Skins/Default/skin-classic.hints +++ b/src/skins-data/Skins/Default/skin-classic.hints diff --git a/src/skins/Skins/Default/skin.hints b/src/skins-data/Skins/Default/skin.hints index ba63ee6..ba63ee6 100644 --- a/src/skins/Skins/Default/skin.hints +++ b/src/skins-data/Skins/Default/skin.hints diff --git a/src/skins/Skins/Default/text.png b/src/skins-data/Skins/Default/text.png Binary files differindex eee0c83..eee0c83 100644 --- a/src/skins/Skins/Default/text.png +++ b/src/skins-data/Skins/Default/text.png diff --git a/src/skins/Skins/Default/titlebar.png b/src/skins-data/Skins/Default/titlebar.png Binary files differindex f1dde49..f1dde49 100644 --- a/src/skins/Skins/Default/titlebar.png +++ b/src/skins-data/Skins/Default/titlebar.png diff --git a/src/skins/Skins/Default/viscolor.txt b/src/skins-data/Skins/Default/viscolor.txt index 64081aa..64081aa 100644 --- a/src/skins/Skins/Default/viscolor.txt +++ b/src/skins-data/Skins/Default/viscolor.txt diff --git a/src/skins/Skins/Default/volume.png b/src/skins-data/Skins/Default/volume.png Binary files differindex 37611da..37611da 100644 --- a/src/skins/Skins/Default/volume.png +++ b/src/skins-data/Skins/Default/volume.png diff --git a/src/skins/Skins/Ivory/balance.png b/src/skins-data/Skins/Ivory/balance.png Binary files differindex fc3c7ac..fc3c7ac 100644 --- a/src/skins/Skins/Ivory/balance.png +++ b/src/skins-data/Skins/Ivory/balance.png diff --git a/src/skins/Skins/Ivory/cbuttons.png b/src/skins-data/Skins/Ivory/cbuttons.png Binary files differindex f5f68e7..f5f68e7 100644 --- a/src/skins/Skins/Ivory/cbuttons.png +++ b/src/skins-data/Skins/Ivory/cbuttons.png diff --git a/src/skins/Skins/Ivory/eq_ex.png b/src/skins-data/Skins/Ivory/eq_ex.png Binary files differindex e231f71..e231f71 100644 --- a/src/skins/Skins/Ivory/eq_ex.png +++ b/src/skins-data/Skins/Ivory/eq_ex.png diff --git a/src/skins/Skins/Ivory/eqmain.png b/src/skins-data/Skins/Ivory/eqmain.png Binary files differindex 2b0b834..2b0b834 100644 --- a/src/skins/Skins/Ivory/eqmain.png +++ b/src/skins-data/Skins/Ivory/eqmain.png diff --git a/src/skins/Skins/Ivory/main.png b/src/skins-data/Skins/Ivory/main.png Binary files differindex d020ea8..d020ea8 100644 --- a/src/skins/Skins/Ivory/main.png +++ b/src/skins-data/Skins/Ivory/main.png diff --git a/src/skins/Skins/Ivory/monoster.png b/src/skins-data/Skins/Ivory/monoster.png Binary files differindex 2746a2f..2746a2f 100644 --- a/src/skins/Skins/Ivory/monoster.png +++ b/src/skins-data/Skins/Ivory/monoster.png diff --git a/src/skins/Skins/Ivory/nums_ex.png b/src/skins-data/Skins/Ivory/nums_ex.png Binary files differindex 5a5260f..5a5260f 100644 --- a/src/skins/Skins/Ivory/nums_ex.png +++ b/src/skins-data/Skins/Ivory/nums_ex.png diff --git a/src/skins/Skins/Ivory/playpaus.png b/src/skins-data/Skins/Ivory/playpaus.png Binary files differindex ef6e329..ef6e329 100644 --- a/src/skins/Skins/Ivory/playpaus.png +++ b/src/skins-data/Skins/Ivory/playpaus.png diff --git a/src/skins/Skins/Ivory/pledit.png b/src/skins-data/Skins/Ivory/pledit.png Binary files differindex a209b14..a209b14 100644 --- a/src/skins/Skins/Ivory/pledit.png +++ b/src/skins-data/Skins/Ivory/pledit.png diff --git a/src/skins/Skins/Ivory/pledit.txt b/src/skins-data/Skins/Ivory/pledit.txt index 8971b33..8971b33 100644 --- a/src/skins/Skins/Ivory/pledit.txt +++ b/src/skins-data/Skins/Ivory/pledit.txt diff --git a/src/skins/Skins/Ivory/posbar.png b/src/skins-data/Skins/Ivory/posbar.png Binary files differindex ba32396..ba32396 100644 --- a/src/skins/Skins/Ivory/posbar.png +++ b/src/skins-data/Skins/Ivory/posbar.png diff --git a/src/skins/Skins/Ivory/shufrep.png b/src/skins-data/Skins/Ivory/shufrep.png Binary files differindex 85b10cb..85b10cb 100644 --- a/src/skins/Skins/Ivory/shufrep.png +++ b/src/skins-data/Skins/Ivory/shufrep.png diff --git a/src/skins/Skins/Ivory/skin.hints b/src/skins-data/Skins/Ivory/skin.hints index 7a8f7b5..7a8f7b5 100644 --- a/src/skins/Skins/Ivory/skin.hints +++ b/src/skins-data/Skins/Ivory/skin.hints diff --git a/src/skins/Skins/Ivory/text.png b/src/skins-data/Skins/Ivory/text.png Binary files differindex d32bb1a..d32bb1a 100644 --- a/src/skins/Skins/Ivory/text.png +++ b/src/skins-data/Skins/Ivory/text.png diff --git a/src/skins/Skins/Ivory/titlebar.png b/src/skins-data/Skins/Ivory/titlebar.png Binary files differindex 827e6a2..827e6a2 100644 --- a/src/skins/Skins/Ivory/titlebar.png +++ b/src/skins-data/Skins/Ivory/titlebar.png diff --git a/src/skins/Skins/Ivory/viscolor.txt b/src/skins-data/Skins/Ivory/viscolor.txt index a497805..a497805 100644 --- a/src/skins/Skins/Ivory/viscolor.txt +++ b/src/skins-data/Skins/Ivory/viscolor.txt diff --git a/src/skins/Skins/Ivory/volume.png b/src/skins-data/Skins/Ivory/volume.png Binary files differindex 63335f6..63335f6 100644 --- a/src/skins/Skins/Ivory/volume.png +++ b/src/skins-data/Skins/Ivory/volume.png diff --git a/src/skins/Skins/Osmosis/balance.png b/src/skins-data/Skins/Osmosis/balance.png Binary files differindex 6f8176f..6f8176f 100644 --- a/src/skins/Skins/Osmosis/balance.png +++ b/src/skins-data/Skins/Osmosis/balance.png diff --git a/src/skins/Skins/Osmosis/cbuttons.png b/src/skins-data/Skins/Osmosis/cbuttons.png Binary files differindex db3002f..db3002f 100644 --- a/src/skins/Skins/Osmosis/cbuttons.png +++ b/src/skins-data/Skins/Osmosis/cbuttons.png diff --git a/src/skins/Skins/Osmosis/eq_ex.png b/src/skins-data/Skins/Osmosis/eq_ex.png Binary files differindex abbfee3..abbfee3 100644 --- a/src/skins/Skins/Osmosis/eq_ex.png +++ b/src/skins-data/Skins/Osmosis/eq_ex.png diff --git a/src/skins/Skins/Osmosis/eqmain.png b/src/skins-data/Skins/Osmosis/eqmain.png Binary files differindex 9035e87..9035e87 100644 --- a/src/skins/Skins/Osmosis/eqmain.png +++ b/src/skins-data/Skins/Osmosis/eqmain.png diff --git a/src/skins/Skins/Osmosis/main.png b/src/skins-data/Skins/Osmosis/main.png Binary files differindex 68933fe..68933fe 100644 --- a/src/skins/Skins/Osmosis/main.png +++ b/src/skins-data/Skins/Osmosis/main.png diff --git a/src/skins/Skins/Osmosis/monoster.png b/src/skins-data/Skins/Osmosis/monoster.png Binary files differindex 84f0bc5..84f0bc5 100644 --- a/src/skins/Skins/Osmosis/monoster.png +++ b/src/skins-data/Skins/Osmosis/monoster.png diff --git a/src/skins/Skins/Osmosis/nums_ex.png b/src/skins-data/Skins/Osmosis/nums_ex.png Binary files differindex fd7f178..fd7f178 100644 --- a/src/skins/Skins/Osmosis/nums_ex.png +++ b/src/skins-data/Skins/Osmosis/nums_ex.png diff --git a/src/skins/Skins/Osmosis/playpaus.png b/src/skins-data/Skins/Osmosis/playpaus.png Binary files differindex bc0c0a6..bc0c0a6 100644 --- a/src/skins/Skins/Osmosis/playpaus.png +++ b/src/skins-data/Skins/Osmosis/playpaus.png diff --git a/src/skins/Skins/Osmosis/pledit.png b/src/skins-data/Skins/Osmosis/pledit.png Binary files differindex fc56bd7..fc56bd7 100644 --- a/src/skins/Skins/Osmosis/pledit.png +++ b/src/skins-data/Skins/Osmosis/pledit.png diff --git a/src/skins/Skins/Osmosis/pledit.txt b/src/skins-data/Skins/Osmosis/pledit.txt index 7c6a658..7c6a658 100644 --- a/src/skins/Skins/Osmosis/pledit.txt +++ b/src/skins-data/Skins/Osmosis/pledit.txt diff --git a/src/skins/Skins/Osmosis/posbar.png b/src/skins-data/Skins/Osmosis/posbar.png Binary files differindex 51f42ad..51f42ad 100644 --- a/src/skins/Skins/Osmosis/posbar.png +++ b/src/skins-data/Skins/Osmosis/posbar.png diff --git a/src/skins/Skins/Osmosis/shufrep.png b/src/skins-data/Skins/Osmosis/shufrep.png Binary files differindex cb33e99..cb33e99 100644 --- a/src/skins/Skins/Osmosis/shufrep.png +++ b/src/skins-data/Skins/Osmosis/shufrep.png diff --git a/src/skins/Skins/Osmosis/skin.hints b/src/skins-data/Skins/Osmosis/skin.hints index 9e924e9..9e924e9 100644 --- a/src/skins/Skins/Osmosis/skin.hints +++ b/src/skins-data/Skins/Osmosis/skin.hints diff --git a/src/skins/Skins/Osmosis/text.png b/src/skins-data/Skins/Osmosis/text.png Binary files differindex 24ddfcf..24ddfcf 100644 --- a/src/skins/Skins/Osmosis/text.png +++ b/src/skins-data/Skins/Osmosis/text.png diff --git a/src/skins/Skins/Osmosis/titlebar.png b/src/skins-data/Skins/Osmosis/titlebar.png Binary files differindex 55a4297..55a4297 100644 --- a/src/skins/Skins/Osmosis/titlebar.png +++ b/src/skins-data/Skins/Osmosis/titlebar.png diff --git a/src/skins/Skins/Osmosis/viscolor.txt b/src/skins-data/Skins/Osmosis/viscolor.txt index 5e00a68..5e00a68 100644 --- a/src/skins/Skins/Osmosis/viscolor.txt +++ b/src/skins-data/Skins/Osmosis/viscolor.txt diff --git a/src/skins/Skins/Osmosis/volume.png b/src/skins-data/Skins/Osmosis/volume.png Binary files differindex bfcc0e7..bfcc0e7 100644 --- a/src/skins/Skins/Osmosis/volume.png +++ b/src/skins-data/Skins/Osmosis/volume.png diff --git a/src/skins/Skins/Refugee/cbuttons.png b/src/skins-data/Skins/Refugee/cbuttons.png Binary files differindex 2eae7e6..2eae7e6 100644 --- a/src/skins/Skins/Refugee/cbuttons.png +++ b/src/skins-data/Skins/Refugee/cbuttons.png diff --git a/src/skins/Skins/Refugee/eq_ex.png b/src/skins-data/Skins/Refugee/eq_ex.png Binary files differindex caeed46..caeed46 100644 --- a/src/skins/Skins/Refugee/eq_ex.png +++ b/src/skins-data/Skins/Refugee/eq_ex.png diff --git a/src/skins/Skins/Refugee/eqmain.png b/src/skins-data/Skins/Refugee/eqmain.png Binary files differindex 51178be..51178be 100644 --- a/src/skins/Skins/Refugee/eqmain.png +++ b/src/skins-data/Skins/Refugee/eqmain.png diff --git a/src/skins/Skins/Refugee/main.png b/src/skins-data/Skins/Refugee/main.png Binary files differindex 7fec481..7fec481 100644 --- a/src/skins/Skins/Refugee/main.png +++ b/src/skins-data/Skins/Refugee/main.png diff --git a/src/skins/Skins/Refugee/monoster.png b/src/skins-data/Skins/Refugee/monoster.png Binary files differindex dab972a..dab972a 100644 --- a/src/skins/Skins/Refugee/monoster.png +++ b/src/skins-data/Skins/Refugee/monoster.png diff --git a/src/skins/Skins/Refugee/numbers.png b/src/skins-data/Skins/Refugee/numbers.png Binary files differindex 1bdb4fa..1bdb4fa 100644 --- a/src/skins/Skins/Refugee/numbers.png +++ b/src/skins-data/Skins/Refugee/numbers.png diff --git a/src/skins/Skins/Refugee/nums_ex.png b/src/skins-data/Skins/Refugee/nums_ex.png Binary files differindex 76d922f..76d922f 100644 --- a/src/skins/Skins/Refugee/nums_ex.png +++ b/src/skins-data/Skins/Refugee/nums_ex.png diff --git a/src/skins/Skins/Refugee/playpaus.png b/src/skins-data/Skins/Refugee/playpaus.png Binary files differindex 5d4a837..5d4a837 100644 --- a/src/skins/Skins/Refugee/playpaus.png +++ b/src/skins-data/Skins/Refugee/playpaus.png diff --git a/src/skins/Skins/Refugee/pledit.png b/src/skins-data/Skins/Refugee/pledit.png Binary files differindex f951c64..f951c64 100644 --- a/src/skins/Skins/Refugee/pledit.png +++ b/src/skins-data/Skins/Refugee/pledit.png diff --git a/src/skins/Skins/Refugee/pledit.txt b/src/skins-data/Skins/Refugee/pledit.txt index 6d7ef4c..6d7ef4c 100644 --- a/src/skins/Skins/Refugee/pledit.txt +++ b/src/skins-data/Skins/Refugee/pledit.txt diff --git a/src/skins/Skins/Refugee/posbar.png b/src/skins-data/Skins/Refugee/posbar.png Binary files differindex 96c2fef..96c2fef 100644 --- a/src/skins/Skins/Refugee/posbar.png +++ b/src/skins-data/Skins/Refugee/posbar.png diff --git a/src/skins/Skins/Refugee/shufrep.png b/src/skins-data/Skins/Refugee/shufrep.png Binary files differindex 2406a2a..2406a2a 100644 --- a/src/skins/Skins/Refugee/shufrep.png +++ b/src/skins-data/Skins/Refugee/shufrep.png diff --git a/src/skins/Skins/Refugee/skin.hints b/src/skins-data/Skins/Refugee/skin.hints index 88c1986..88c1986 100644 --- a/src/skins/Skins/Refugee/skin.hints +++ b/src/skins-data/Skins/Refugee/skin.hints diff --git a/src/skins/Skins/Refugee/text.png b/src/skins-data/Skins/Refugee/text.png Binary files differindex 6bed67b..6bed67b 100644 --- a/src/skins/Skins/Refugee/text.png +++ b/src/skins-data/Skins/Refugee/text.png diff --git a/src/skins/Skins/Refugee/titlebar.png b/src/skins-data/Skins/Refugee/titlebar.png Binary files differindex 4a052dd..4a052dd 100644 --- a/src/skins/Skins/Refugee/titlebar.png +++ b/src/skins-data/Skins/Refugee/titlebar.png diff --git a/src/skins/Skins/Refugee/viscolor.txt b/src/skins-data/Skins/Refugee/viscolor.txt index 5744ead..5744ead 100644 --- a/src/skins/Skins/Refugee/viscolor.txt +++ b/src/skins-data/Skins/Refugee/viscolor.txt diff --git a/src/skins/Skins/Refugee/volume.png b/src/skins-data/Skins/Refugee/volume.png Binary files differindex ac3da03..ac3da03 100644 --- a/src/skins/Skins/Refugee/volume.png +++ b/src/skins-data/Skins/Refugee/volume.png diff --git a/src/skins/Skins/TinyPlayer/balance.png b/src/skins-data/Skins/TinyPlayer/balance.png Binary files differindex 1493934..1493934 100644 --- a/src/skins/Skins/TinyPlayer/balance.png +++ b/src/skins-data/Skins/TinyPlayer/balance.png diff --git a/src/skins/Skins/TinyPlayer/cbuttons.png b/src/skins-data/Skins/TinyPlayer/cbuttons.png Binary files differindex 40dea8c..40dea8c 100644 --- a/src/skins/Skins/TinyPlayer/cbuttons.png +++ b/src/skins-data/Skins/TinyPlayer/cbuttons.png diff --git a/src/skins/Skins/TinyPlayer/eq_ex.png b/src/skins-data/Skins/TinyPlayer/eq_ex.png Binary files differindex a693a84..a693a84 100644 --- a/src/skins/Skins/TinyPlayer/eq_ex.png +++ b/src/skins-data/Skins/TinyPlayer/eq_ex.png diff --git a/src/skins/Skins/TinyPlayer/eqmain.png b/src/skins-data/Skins/TinyPlayer/eqmain.png Binary files differindex fab90e8..fab90e8 100644 --- a/src/skins/Skins/TinyPlayer/eqmain.png +++ b/src/skins-data/Skins/TinyPlayer/eqmain.png diff --git a/src/skins/Skins/TinyPlayer/main.png b/src/skins-data/Skins/TinyPlayer/main.png Binary files differindex c484d15..c484d15 100644 --- a/src/skins/Skins/TinyPlayer/main.png +++ b/src/skins-data/Skins/TinyPlayer/main.png diff --git a/src/skins/Skins/TinyPlayer/monoster.png b/src/skins-data/Skins/TinyPlayer/monoster.png Binary files differindex 84f0bc5..84f0bc5 100644 --- a/src/skins/Skins/TinyPlayer/monoster.png +++ b/src/skins-data/Skins/TinyPlayer/monoster.png diff --git a/src/skins/Skins/TinyPlayer/nums_ex.png b/src/skins-data/Skins/TinyPlayer/nums_ex.png Binary files differindex fd7f178..fd7f178 100644 --- a/src/skins/Skins/TinyPlayer/nums_ex.png +++ b/src/skins-data/Skins/TinyPlayer/nums_ex.png diff --git a/src/skins/Skins/TinyPlayer/playpaus.png b/src/skins-data/Skins/TinyPlayer/playpaus.png Binary files differindex bc0c0a6..bc0c0a6 100644 --- a/src/skins/Skins/TinyPlayer/playpaus.png +++ b/src/skins-data/Skins/TinyPlayer/playpaus.png diff --git a/src/skins/Skins/TinyPlayer/pledit.png b/src/skins-data/Skins/TinyPlayer/pledit.png Binary files differindex 6351be8..6351be8 100644 --- a/src/skins/Skins/TinyPlayer/pledit.png +++ b/src/skins-data/Skins/TinyPlayer/pledit.png diff --git a/src/skins/Skins/TinyPlayer/pledit.txt b/src/skins-data/Skins/TinyPlayer/pledit.txt index 7c6a658..7c6a658 100644 --- a/src/skins/Skins/TinyPlayer/pledit.txt +++ b/src/skins-data/Skins/TinyPlayer/pledit.txt diff --git a/src/skins/Skins/TinyPlayer/posbar.png b/src/skins-data/Skins/TinyPlayer/posbar.png Binary files differindex cdb3677..cdb3677 100644 --- a/src/skins/Skins/TinyPlayer/posbar.png +++ b/src/skins-data/Skins/TinyPlayer/posbar.png diff --git a/src/skins/Skins/TinyPlayer/shufrep.png b/src/skins-data/Skins/TinyPlayer/shufrep.png Binary files differindex d98aa90..d98aa90 100644 --- a/src/skins/Skins/TinyPlayer/shufrep.png +++ b/src/skins-data/Skins/TinyPlayer/shufrep.png diff --git a/src/skins/Skins/TinyPlayer/skin.hints b/src/skins-data/Skins/TinyPlayer/skin.hints index eebb4fa..eebb4fa 100644 --- a/src/skins/Skins/TinyPlayer/skin.hints +++ b/src/skins-data/Skins/TinyPlayer/skin.hints diff --git a/src/skins/Skins/TinyPlayer/text.png b/src/skins-data/Skins/TinyPlayer/text.png Binary files differindex 24ddfcf..24ddfcf 100644 --- a/src/skins/Skins/TinyPlayer/text.png +++ b/src/skins-data/Skins/TinyPlayer/text.png diff --git a/src/skins/Skins/TinyPlayer/titlebar.png b/src/skins-data/Skins/TinyPlayer/titlebar.png Binary files differindex acd0503..acd0503 100644 --- a/src/skins/Skins/TinyPlayer/titlebar.png +++ b/src/skins-data/Skins/TinyPlayer/titlebar.png diff --git a/src/skins/Skins/TinyPlayer/viscolor.txt b/src/skins-data/Skins/TinyPlayer/viscolor.txt index 5e00a68..5e00a68 100644 --- a/src/skins/Skins/TinyPlayer/viscolor.txt +++ b/src/skins-data/Skins/TinyPlayer/viscolor.txt diff --git a/src/skins/Skins/TinyPlayer/volume.png b/src/skins-data/Skins/TinyPlayer/volume.png Binary files differindex 9bf72ea..9bf72ea 100644 --- a/src/skins/Skins/TinyPlayer/volume.png +++ b/src/skins-data/Skins/TinyPlayer/volume.png diff --git a/src/skins-qt/Makefile b/src/skins-qt/Makefile new file mode 100644 index 0000000..491ff76 --- /dev/null +++ b/src/skins-qt/Makefile @@ -0,0 +1,44 @@ +PLUGIN = skins-qt${PLUGIN_SUFFIX} + +SRCS = actions.cc \ + button.cc \ + dock.cc \ + drag-handle.cc \ + eq-graph.cc \ + eq-slider.cc \ + equalizer.cc \ + hslider.cc \ + main.cc \ + menurow.cc \ + menus.cc \ + monostereo.cc \ + number.cc \ + playlist.cc \ + playlist-slider.cc \ + playlist-widget.cc \ + playstatus.cc \ + plugin.cc \ + plugin-window.cc \ + skin.cc \ + skin-ini.cc \ + skins_cfg.cc \ + skinselector.cc \ + svis.cc \ + textbox.cc \ + util.cc \ + view.cc \ + vis-callbacks.cc \ + vis.cc \ + widget.cc \ + window.cc + +include ../../buildsys.mk +include ../../extra.mk + +plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR} + +LD = ${CXX} + +CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../.. ${GLIB_CFLAGS} ${QT_CFLAGS} +CFLAGS += ${PLUGIN_CFLAGS} +LIBS += -lm ${GLIB_LIBS} ${QT_LIBS} -laudqt diff --git a/src/skins-qt/actions-mainwin.h b/src/skins-qt/actions-mainwin.h new file mode 100644 index 0000000..a62eb42 --- /dev/null +++ b/src/skins-qt/actions-mainwin.h @@ -0,0 +1,31 @@ +/* Audacious - Cross-platform multimedia player + * Copyright (C) 2005-2007 Audacious development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#ifndef SKINS_ACTIONS_MAINWIN_H +#define SKINS_ACTIONS_MAINWIN_H + +void action_ab_clear (); +void action_ab_set (); +void action_play_file (); +void action_play_folder (); +void action_play_location (); +void action_playlist_manager (); +void action_search_tool (); + +#endif /* SKINS_ACTIONS_MAINWIN_H */ diff --git a/src/skins-qt/actions-playlist.h b/src/skins-qt/actions-playlist.h new file mode 100644 index 0000000..8f530b4 --- /dev/null +++ b/src/skins-qt/actions-playlist.h @@ -0,0 +1,83 @@ +/* Audacious - Cross-platform multimedia player + * Copyright (C) 2005-2007 Audacious development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#ifndef SKINS_ACTIONS_PLAYLIST_H +#define SKINS_ACTIONS_PLAYLIST_H + +void action_playlist_refresh_list (); + +void action_playlist_play (); +void action_playlist_new (); +void action_playlist_prev (); +void action_playlist_next (); +void action_playlist_rename (); +void action_playlist_delete (); + +void action_playlist_invert_selection (); +void action_playlist_select_all (); +void action_playlist_select_none (); + +void action_playlist_clear_queue (); +void action_playlist_remove_unavailable (); +void action_playlist_remove_dupes_by_title (); +void action_playlist_remove_dupes_by_filename (); +void action_playlist_remove_dupes_by_full_path (); +void action_playlist_remove_all (); +void action_playlist_remove_selected (); +void action_playlist_remove_unselected (); + +void action_playlist_copy (); +void action_playlist_cut (); +void action_playlist_paste (); + +void action_playlist_add_url (); +void action_playlist_add_files (); +void action_playlist_add_folder (); + +void action_playlist_randomize_list (); +void action_playlist_reverse_list (); + +void action_playlist_sort_by_title (); +void action_playlist_sort_by_album (); +void action_playlist_sort_by_artist (); +void action_playlist_sort_by_album_artist (); +void action_playlist_sort_by_length (); +void action_playlist_sort_by_genre (); +void action_playlist_sort_by_filename (); +void action_playlist_sort_by_full_path (); +void action_playlist_sort_by_date (); +void action_playlist_sort_by_track_number (); +void action_playlist_sort_by_custom_title (); + +void action_playlist_sort_selected_by_title (); +void action_playlist_sort_selected_by_album (); +void action_playlist_sort_selected_by_artist (); +void action_playlist_sort_selected_by_album_artist (); +void action_playlist_sort_selected_by_length (); +void action_playlist_sort_selected_by_genre (); +void action_playlist_sort_selected_by_filename (); +void action_playlist_sort_selected_by_full_path (); +void action_playlist_sort_selected_by_date (); +void action_playlist_sort_selected_by_track_number (); +void action_playlist_sort_selected_by_custom_title (); + +void action_playlist_track_info (); +void action_queue_toggle (); + +#endif /* SKINS_ACTIONS_PLAYLIST_H */ diff --git a/src/skins-qt/actions.cc b/src/skins-qt/actions.cc new file mode 100644 index 0000000..3b2695d --- /dev/null +++ b/src/skins-qt/actions.cc @@ -0,0 +1,295 @@ +/* Audacious - Cross-platform multimedia player + * Copyright (C) 2005-2011 Audacious development team. + * + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include "actions-mainwin.h" +#include "actions-playlist.h" +#include "main.h" +#include "plugin-window.h" + +#include <libaudcore/drct.h> +#include <libaudcore/i18n.h> +#include <libaudcore/playlist.h> +#include <libaudcore/plugins.h> +#include <libaudqt/libaudqt.h> + +#define ACTIVE (aud_playlist_get_active ()) + +void action_ab_clear () +{ + mainwin_show_status_message (_("Repeat points cleared.")); + aud_drct_set_ab_repeat (-1, -1); +} + +void action_ab_set () +{ + if (aud_drct_get_length () > 0) + { + int a, b; + aud_drct_get_ab_repeat (a, b); + + if (a < 0 || b >= 0) + { + a = aud_drct_get_time (); + b = -1; + mainwin_show_status_message (_("Repeat point A set.")); + } + else + { + b = aud_drct_get_time (); + mainwin_show_status_message (_("Repeat point B set.")); + } + + aud_drct_set_ab_repeat (a, b); + } +} + +void action_play_file () + { audqt::fileopener_show (audqt::FileMode::Open); } +void action_play_folder () + { audqt::fileopener_show (audqt::FileMode::OpenFolder); } +void action_play_location () + { audqt::urlopener_show (true); } + +void action_playlist_manager () +{ + PluginHandle * manager = aud_plugin_lookup_basename ("playlist-manager-qt"); + if (manager) + { + aud_plugin_enable (manager, true); + focus_plugin_window (manager); + } +} + +void action_search_tool () +{ + PluginHandle * search = aud_plugin_lookup_basename ("search-tool"); + if (search) + { + aud_plugin_enable (search, true); + focus_plugin_window (search); + } +} + +void action_playlist_refresh_list () + { aud_playlist_rescan (ACTIVE); } +void action_playlist_play () + { aud_playlist_play (ACTIVE); } + +void action_playlist_new () +{ + int playlist = aud_playlist_get_active () + 1; + aud_playlist_insert (playlist); + aud_playlist_set_active (playlist); +} + +void action_playlist_prev () +{ + int playlist = ACTIVE; + if (playlist > 0) + aud_playlist_set_active (playlist - 1); + else + { + int count = aud_playlist_count (); + if (count > 1) + aud_playlist_set_active (count - 1); + } +} + +void action_playlist_next () +{ + int playlist = ACTIVE; + int count = aud_playlist_count (); + if (playlist + 1 < count) + aud_playlist_set_active (playlist + 1); + else if (count > 1) + aud_playlist_set_active (0); +} + +void action_playlist_rename () + { audqt::playlist_show_rename (ACTIVE); } +void action_playlist_delete () + { audqt::playlist_confirm_delete (ACTIVE); } + +void action_playlist_invert_selection () +{ + int playlist = ACTIVE; + int entries = aud_playlist_entry_count (playlist); + for (int entry = 0; entry < entries; entry ++) + aud_playlist_entry_set_selected (playlist, entry, + ! aud_playlist_entry_get_selected (playlist, entry)); +} + +void action_playlist_select_all () + { aud_playlist_select_all (ACTIVE, true); } +void action_playlist_select_none () + { aud_playlist_select_all (ACTIVE, false); } + +void action_playlist_clear_queue () +{ + int playlist = ACTIVE; + aud_playlist_queue_delete (playlist, 0, aud_playlist_queue_count (playlist)); +} + +void action_playlist_remove_unavailable () + { aud_playlist_remove_failed (ACTIVE); } +void action_playlist_remove_dupes_by_title () + { aud_playlist_remove_duplicates_by_scheme (ACTIVE, Playlist::Title); } +void action_playlist_remove_dupes_by_filename () + { aud_playlist_remove_duplicates_by_scheme (ACTIVE, Playlist::Filename); } +void action_playlist_remove_dupes_by_full_path () + { aud_playlist_remove_duplicates_by_scheme (ACTIVE, Playlist::Path); } + +void action_playlist_remove_all () +{ + int playlist = ACTIVE; + aud_playlist_entry_delete (playlist, 0, aud_playlist_entry_count (playlist)); +} + +void action_playlist_remove_selected () + { aud_playlist_delete_selected (ACTIVE); } + +void action_playlist_remove_unselected () +{ + action_playlist_invert_selection (); + action_playlist_remove_selected (); + action_playlist_select_all (); +} + +void action_playlist_copy () +{ +#if 0 + GtkClipboard * clip = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); + Index<char> list = audgui_urilist_create_from_selected (ACTIVE); + + if (list.len ()) + gtk_clipboard_set_text (clip, list.begin (), list.len ()); +#endif +} + +void action_playlist_cut () +{ + action_playlist_copy (); + action_playlist_remove_selected (); +} + +void action_playlist_paste () +{ +#if 0 + GtkClipboard * clip = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); + char * list = gtk_clipboard_wait_for_text (clip); + + if (list) + { + int playlist = ACTIVE; + audgui_urilist_insert (playlist, aud_playlist_get_focus (playlist), list); + g_free (list); + } +#endif +} + +void action_playlist_add_url () + { audqt::urlopener_show (false); } +void action_playlist_add_files () + { audqt::fileopener_show (audqt::FileMode::Add ); } +void action_playlist_add_folder () + { audqt::fileopener_show (audqt::FileMode::AddFolder ); } + +void action_playlist_randomize_list () + { aud_playlist_randomize (ACTIVE); } +void action_playlist_reverse_list () + { aud_playlist_reverse (ACTIVE); } + +void action_playlist_sort_by_title () + { aud_playlist_sort_by_scheme (ACTIVE, Playlist::Title); } +void action_playlist_sort_by_album () + { aud_playlist_sort_by_scheme (ACTIVE, Playlist::Album); } +void action_playlist_sort_by_artist () + { aud_playlist_sort_by_scheme (ACTIVE, Playlist::Artist); } +void action_playlist_sort_by_album_artist () + { aud_playlist_sort_by_scheme (ACTIVE, Playlist::AlbumArtist); } +void action_playlist_sort_by_length () + { aud_playlist_sort_by_scheme (ACTIVE, Playlist::Length); } +void action_playlist_sort_by_genre () + { aud_playlist_sort_by_scheme (ACTIVE, Playlist::Genre); } +void action_playlist_sort_by_filename () + { aud_playlist_sort_by_scheme (ACTIVE, Playlist::Filename); } +void action_playlist_sort_by_full_path () + { aud_playlist_sort_by_scheme (ACTIVE, Playlist::Path); } +void action_playlist_sort_by_date () + { aud_playlist_sort_by_scheme (ACTIVE, Playlist::Date); } +void action_playlist_sort_by_track_number () + { aud_playlist_sort_by_scheme (ACTIVE, Playlist::Track); } +void action_playlist_sort_by_custom_title () + { aud_playlist_sort_by_scheme (ACTIVE, Playlist::FormattedTitle); } + +void action_playlist_sort_selected_by_title () + { aud_playlist_sort_selected_by_scheme (ACTIVE, Playlist::Title); } +void action_playlist_sort_selected_by_album () + { aud_playlist_sort_selected_by_scheme (ACTIVE, Playlist::Album); } +void action_playlist_sort_selected_by_artist () + { aud_playlist_sort_selected_by_scheme (ACTIVE, Playlist::Artist); } +void action_playlist_sort_selected_by_album_artist () + { aud_playlist_sort_selected_by_scheme (ACTIVE, Playlist::AlbumArtist); } +void action_playlist_sort_selected_by_length () + { aud_playlist_sort_selected_by_scheme (ACTIVE, Playlist::Length); } +void action_playlist_sort_selected_by_genre () + { aud_playlist_sort_selected_by_scheme (ACTIVE, Playlist::Genre); } +void action_playlist_sort_selected_by_filename () + { aud_playlist_sort_selected_by_scheme (ACTIVE, Playlist::Filename); } +void action_playlist_sort_selected_by_full_path () + { aud_playlist_sort_selected_by_scheme (ACTIVE, Playlist::Path); } +void action_playlist_sort_selected_by_date () + { aud_playlist_sort_selected_by_scheme (ACTIVE, Playlist::Date); } +void action_playlist_sort_selected_by_track_number () + { aud_playlist_sort_selected_by_scheme (ACTIVE, Playlist::Track); } +void action_playlist_sort_selected_by_custom_title () + { aud_playlist_sort_selected_by_scheme (ACTIVE, Playlist::FormattedTitle); } + +void action_playlist_track_info () +{ + int playlist = ACTIVE; + audqt::infowin_show (playlist, aud_playlist_get_focus (playlist)); +} + +void action_queue_toggle () +{ + int playlist = ACTIVE; + int focus = aud_playlist_get_focus (playlist); + if (focus == -1) + return; + + /* make sure focused row is selected */ + if (! aud_playlist_entry_get_selected (playlist, focus)) + { + aud_playlist_select_all (playlist, false); + aud_playlist_entry_set_selected (playlist, focus, true); + } + + int at = aud_playlist_queue_find_entry (playlist, focus); + if (at == -1) + aud_playlist_queue_insert_selected (playlist, -1); + else + aud_playlist_queue_delete_selected (playlist); +} diff --git a/src/skins-qt/button.cc b/src/skins-qt/button.cc new file mode 100644 index 0000000..11a94f8 --- /dev/null +++ b/src/skins-qt/button.cc @@ -0,0 +1,132 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2011 John Lindgren + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include "skins_cfg.h" +#include "button.h" + +void Button::draw (QPainter & cr) +{ + switch (m_type) + { + case Normal: + if (m_pressed) + skin_draw_pixbuf (cr, m_si2, m_px, m_py, 0, 0, m_w, m_h); + else + skin_draw_pixbuf (cr, m_si1, m_nx, m_ny, 0, 0, m_w, m_h); + break; + case Toggle: + if (m_active) + { + if (m_pressed) + skin_draw_pixbuf (cr, m_si2, m_ppx, m_ppy, 0, 0, m_w, m_h); + else + skin_draw_pixbuf (cr, m_si1, m_pnx, m_pny, 0, 0, m_w, m_h); + } + else + { + if (m_pressed) + skin_draw_pixbuf (cr, m_si2, m_px, m_py, 0, 0, m_w, m_h); + else + skin_draw_pixbuf (cr, m_si1, m_nx, m_ny, 0, 0, m_w, m_h); + } + break; + case Small: + break; + } +} + +bool Button::button_press (QMouseEvent * event) +{ + /* pass events through to the parent widget only if neither the press nor + * release signals are connected; sending one and not the other causes + * problems (in particular with dragging windows around) */ + if (event->button () == Qt::LeftButton && (press || release)) + { + m_pressed = true; + if (press) + press (this, event); + } + else if (event->button () == Qt::RightButton && (rpress || rrelease)) + { + m_rpressed = true; + if (rpress) + rpress (this, event); + } + else + return false; + + if (m_type != Small) + queue_draw (); + + return true; +} + +bool Button::button_release (QMouseEvent * event) +{ + if (event->button () == Qt::LeftButton && (press || release)) + { + if (! m_pressed) + return true; + + m_pressed = false; + if (m_type == Toggle) + m_active = ! m_active; + if (release) + release (this, event); + } + else if (event->button () == Qt::RightButton && (rpress || rrelease)) + { + if (! m_rpressed) + return true; + + m_rpressed = false; + if (rrelease) + rrelease (this, event); + } + else + return false; + + if (m_type != Small) + queue_draw (); + + return true; +} + +Button::Button (Type type, int w, int h, int nx, int ny, int px, int py, + int pnx, int pny, int ppx, int ppy, SkinPixmapId si1, SkinPixmapId si2) : + m_type (type), + m_w (w), m_h (h), + m_nx (nx), m_ny (ny), m_px (px), m_py (py), + m_pnx (pnx), m_pny (pny), m_ppx (ppx), m_ppy (ppy), + m_si1 (si1), m_si2 (si2) +{ + set_scale (config.scale); + add_input (w, h, false, type != Small); +} + +void Button::set_active (bool active) +{ + if (m_active != active) + { + m_active = active; + queue_draw (); + } +} diff --git a/src/skins-qt/button.h b/src/skins-qt/button.h new file mode 100644 index 0000000..5d09519 --- /dev/null +++ b/src/skins-qt/button.h @@ -0,0 +1,78 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2011 John Lindgren + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#ifndef SKINS_UI_SKINNED_BUTTON_H +#define SKINS_UI_SKINNED_BUTTON_H + +#include "widget.h" +#include "skin.h" + +class Button; + +typedef void (* ButtonCB) (Button * button, QMouseEvent * event); + +class Button : public Widget +{ +public: + // transparent button + Button (int w, int h) : + Button (Small, w, h, 0, 0, 0, 0, 0, 0, 0, 0, SKIN_MAIN, SKIN_MAIN) {} + + // basic skinned button + Button (int w, int h, int nx, int ny, int px, int py, SkinPixmapId si1, SkinPixmapId si2) : + Button (Normal, w, h, nx, ny, px, py, 0, 0, 0, 0, si1, si2) {} + + // skinned toggle button + Button (int w, int h, int nx, int ny, int px, int py, int pnx, int pny, + int ppx, int ppy, SkinPixmapId si1, SkinPixmapId si2) : + Button (Toggle, w, h, nx, ny, px, py, pnx, pny, ppx, ppy, si1, si2) {} + + void on_press (ButtonCB callback) { press = callback; } + void on_release (ButtonCB callback) { release = callback; } + void on_rpress (ButtonCB callback) { rpress = callback; } + void on_rrelease (ButtonCB callback) { rrelease = callback; } + + bool get_active () { return m_active; } + void set_active (bool active); + +private: + enum Type {Normal, Toggle, Small}; + + Button (Type type, int w, int h, int nx, int ny, int px, int py, int pnx, + int pny, int ppx, int ppy, SkinPixmapId si1, SkinPixmapId si2); + + void draw (QPainter & cr); + bool button_press (QMouseEvent * event); + bool button_release (QMouseEvent * event); + + Type m_type; + int m_w, m_h; + int m_nx, m_ny, m_px, m_py; + int m_pnx, m_pny, m_ppx, m_ppy; + SkinPixmapId m_si1, m_si2; + + bool m_pressed = false, m_rpressed = false, m_active = false; + + ButtonCB press = nullptr, release = nullptr; + ButtonCB rpress = nullptr, rrelease = nullptr; +}; + +#endif diff --git a/src/skins-qt/dnd.h b/src/skins-qt/dnd.h new file mode 100644 index 0000000..130a52f --- /dev/null +++ b/src/skins-qt/dnd.h @@ -0,0 +1,56 @@ +/* Audacious - Cross-platform multimedia player + * Copyright (C) 2005-2011 Audacious development team + * + * Based on BMP: + * Copyright (C) 2003-2004 BMP development team + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#ifndef SKINS_DND_H +#define SKINS_DND_H + +/* Designate dropped data types that we know and care about */ +enum { + DROP_STRING, + DROP_PLAINTEXT, + DROP_URLENCODED, + DROP_SKIN, + DROP_FONT +}; + +#if 0 +/* Drag data format listing for gtk_drag_dest_set() */ +static const GtkTargetEntry drop_types[] = { + {(char *) "text/plain", 0, DROP_PLAINTEXT}, + {(char *) "text/uri-list", 0, DROP_URLENCODED}, + {(char *) "STRING", 0, DROP_STRING}, + {(char *) "interface/x-winamp-skin", 0, DROP_SKIN}, + {(char *) "application/x-font-ttf", 0, DROP_FONT}, +}; + +static inline void drag_dest_set (GtkWidget * widget) +{ + gtk_drag_dest_set (widget, (GtkDestDefaults) (GTK_DEST_DEFAULT_MOTION | + GTK_DEST_DEFAULT_DROP), drop_types, aud::n_elems (drop_types), + (GdkDragAction) (GDK_ACTION_COPY | GDK_ACTION_MOVE)); +} +#endif + +#endif /* SKINS_DND_H */ diff --git a/src/skins/ui_dock.cc b/src/skins-qt/dock.cc index dfa302c..54bcbfe 100644 --- a/src/skins/ui_dock.cc +++ b/src/skins-qt/dock.cc @@ -38,28 +38,27 @@ #include <stdlib.h> -#include "ui_dock.h" +#include "window.h" #define SNAP_DISTANCE 10 enum { - DOCK_TYPE_LEFT = 1 << 0, - DOCK_TYPE_RIGHT = 1 << 1, - DOCK_TYPE_TOP = 1 << 2, - DOCK_TYPE_BOTTOM = 1 << 3 + DOCK_TYPE_LEFT = 1 << 0, + DOCK_TYPE_RIGHT = 1 << 1, + DOCK_TYPE_TOP = 1 << 2, + DOCK_TYPE_BOTTOM = 1 << 3 }; #define DOCK_TYPE_ANY (DOCK_TYPE_LEFT | DOCK_TYPE_RIGHT | DOCK_TYPE_TOP | DOCK_TYPE_BOTTOM) typedef struct { - GtkWidget * window; + Window * window; int * x, * y; int w, h; - gboolean main; - gboolean docked; + bool docked; } DockWindow; -static GSList * windows; +static DockWindow windows[N_WINDOWS]; static int last_x, last_y; static inline int least_abs (int a, int b) @@ -67,111 +66,78 @@ static inline int least_abs (int a, int b) return (abs (a) < abs (b)) ? a : b; } -static DockWindow * find_window (GSList * list, GtkWidget * window) +void dock_add_window (int id, Window * window, int * x, int * y, int w, int h) { - for (GSList * node = list; node; node = node->next) - { - DockWindow * dw = (DockWindow *) node->data; - if (dw->window == window) - return dw; - } + DockWindow & dw = windows[id]; - return nullptr; -} - -void dock_add_window (GtkWidget * window, int * x, int * y, int w, int h, - gboolean main) -{ - DockWindow * dw = g_slice_new0 (DockWindow); - dw->window = window; - dw->x = x; - dw->y = y; - dw->w = w; - dw->h = h; - dw->main = main; - - windows = g_slist_prepend (windows, dw); + dw.window = window; + dw.x = x; + dw.y = y; + dw.w = w; + dw.h = h; } -void dock_remove_window (GtkWidget * window) +void dock_remove_window (int id) { - DockWindow * dw = find_window (windows, window); - g_return_if_fail (dw); - - windows = g_slist_remove (windows, dw); - g_slice_free (DockWindow, dw); + windows[id].window = nullptr; } -static void dock_sync (void) +static void dock_sync () { - for (GSList * node = windows; node; node = node->next) + for (DockWindow & dw : windows) { - DockWindow * dw = (DockWindow *) node->data; - gtk_window_get_position ((GtkWindow *) dw->window, dw->x, dw->y); + if (dw.window) + dw.window->getPosition (dw.x, dw.y); } } -static void clear_docked (void) +static void clear_docked () { - for (GSList * node = windows; node; node = node->next) - { - DockWindow * dw = (DockWindow *) node->data; - dw->docked = FALSE; - } + for (DockWindow & dw : windows) + dw.docked = false; } -static gboolean is_docked (DockWindow * dw, DockWindow * base, int type) +static bool is_docked (DockWindow & dw, DockWindow & base, int type) { - if ((type & DOCK_TYPE_LEFT) && * dw->x + dw->w == * base->x) - return TRUE; - if ((type & DOCK_TYPE_RIGHT) && * dw->x == * base->x + base->w) - return TRUE; - if ((type & DOCK_TYPE_TOP) && * dw->y + dw->h == * base->y) - return TRUE; - if ((type & DOCK_TYPE_BOTTOM) && * dw->y == * base->y + base->h) - return TRUE; - - return FALSE; + return ((type & DOCK_TYPE_LEFT) && * dw.x + dw.w == * base.x) || + ((type & DOCK_TYPE_RIGHT) && * dw.x == * base.x + base.w) || + ((type & DOCK_TYPE_TOP) && * dw.y + dw.h == * base.y) || + ((type & DOCK_TYPE_BOTTOM) && * dw.y == * base.y + base.h); } -static void find_docked (DockWindow * base, int type) +static void find_docked (DockWindow & base, int type) { - for (GSList * node = windows; node; node = node->next) + for (DockWindow & dw : windows) { - DockWindow * dw = (DockWindow *) node->data; - if (dw->docked || dw == base) + if (dw.docked || & dw == & base) continue; - dw->docked = is_docked (dw, base, type); - if (dw->docked) + dw.docked = is_docked (dw, base, type); + if (dw.docked) find_docked (dw, type); } } -static void invert_docked (void) +static void invert_docked () { - for (GSList * node = windows; node; node = node->next) - { - DockWindow * dw = (DockWindow *) node->data; - dw->docked = ! dw->docked; - } + for (DockWindow & dw : windows) + dw.docked = ! dw.docked; } -void dock_set_size (GtkWidget * window, int w, int h) +void dock_set_size (int id, int w, int h) { - DockWindow * base = find_window (windows, window); - g_return_if_fail (base); + DockWindow & base = windows[id]; dock_sync (); - if (h != base->h) + if (h != base.h) { /* 1. Find the windows docked below this one. */ clear_docked (); find_docked (base, DOCK_TYPE_BOTTOM); - if (h < base->h) + if (h < base.h) { /* 2. This part is tricky. By flipping the docked flag on all the windows, we consider the windows not docked to this one as a @@ -185,10 +151,9 @@ void dock_set_size (GtkWidget * window, int w, int h) invert_docked (); - for (GSList * node = windows; node; node = node->next) + for (DockWindow & dw : windows) { - DockWindow * dw = (DockWindow *) node->data; - if (! dw->docked || dw == base) + if (! dw.docked || & dw == & base) continue; find_docked (dw, DOCK_TYPE_BOTTOM); @@ -199,32 +164,31 @@ void dock_set_size (GtkWidget * window, int w, int h) /* 3. Move the docked windows by the difference in height. */ - for (GSList * node = windows; node; node = node->next) + for (DockWindow & dw : windows) { - DockWindow * dw = (DockWindow *) node->data; - if (! dw->docked) + if (! dw.docked) continue; - * dw->y += h - base->h; - gtk_window_move ((GtkWindow *) dw->window, * dw->x, * dw->y); + * dw.y += h - base.h; + if (dw.window) + dw.window->move (* dw.x, * dw.y); } } - if (w != base->w) + if (w != base.w) { /* 4. Repeat the process for the windows docked to the right. */ clear_docked (); find_docked (base, DOCK_TYPE_RIGHT); - if (w < base->w) + if (w < base.w) { invert_docked (); - for (GSList * node = windows; node; node = node->next) + for (DockWindow & dw : windows) { - DockWindow * dw = (DockWindow *) node->data; - if (! dw->docked || dw == base) + if (! dw.docked || & dw == & base) continue; find_docked (dw, DOCK_TYPE_RIGHT); @@ -233,27 +197,26 @@ void dock_set_size (GtkWidget * window, int w, int h) invert_docked (); } - for (GSList * node = windows; node; node = node->next) + for (DockWindow & dw : windows) { - DockWindow * dw = (DockWindow *) node->data; - if (! dw->docked) + if (! dw.docked) continue; - * dw->x += w - base->w; - gtk_window_move ((GtkWindow *) dw->window, * dw->x, * dw->y); + * dw.x += w - base.w; + if (dw.window) + dw.window->move (* dw.x, * dw.y); } } /* 5. Set the window size. (The actual resize is done by the caller.) */ - base->w = w; - base->h = h; + base.w = w; + base.h = h; } -void dock_move_start (GtkWidget * window, int x, int y) +void dock_move_start (int id, int x, int y) { - DockWindow * dw = find_window (windows, window); - g_return_if_fail (dw); + DockWindow & dw = windows[id]; dock_sync (); @@ -263,8 +226,8 @@ void dock_move_start (GtkWidget * window, int x, int y) /* 1. If this is the main window, find the windows docked to it. */ clear_docked (); - dw->docked = TRUE; - if (dw->main) + dw.docked = true; + if (id == WINDOW_MAIN) find_docked (dw, DOCK_TYPE_ANY); } @@ -281,14 +244,13 @@ void dock_move (int x, int y) hori = x - last_x; vert = y - last_y; - for (GSList * node = windows; node; node = node->next) + for (DockWindow & dw : windows) { - DockWindow * dw = (DockWindow *) node->data; - if (! dw->docked) + if (! dw.docked) continue; - * dw->x += hori; - * dw->y += vert; + * dw.x += hori; + * dw.y += vert; } last_x = x; @@ -302,6 +264,7 @@ void dock_move (int x, int y) hori = SNAP_DISTANCE + 1; vert = SNAP_DISTANCE + 1; +#if 0 GdkScreen * screen = gdk_screen_get_default (); int monitors = gdk_screen_get_n_monitors (screen); @@ -310,43 +273,41 @@ void dock_move (int x, int y) GdkRectangle rect; gdk_screen_get_monitor_geometry (screen, m, & rect); - for (GSList * node = windows; node; node = node->next) + for (DockWindow & dw : windows) { - DockWindow * dw = (DockWindow *) node->data; - if (! dw->docked) + if (! dw.docked) continue; /* We only test half the combinations here, as it is not very helpful to have e.g. the right edge of a window touching the left edge of a monitor (think about it). */ - hori = least_abs (hori, rect.x - * dw->x); - hori = least_abs (hori, (rect.x + rect.width) - (* dw->x + dw->w)); - vert = least_abs (vert, rect.y - * dw->y); - vert = least_abs (vert, (rect.y + rect.height) - (* dw->y + dw->h)); + hori = least_abs (hori, rect.x - * dw.x); + hori = least_abs (hori, (rect.x + rect.width) - (* dw.x + dw.w)); + vert = least_abs (vert, rect.y - * dw.y); + vert = least_abs (vert, (rect.y + rect.height) - (* dw.y + dw.h)); } } +#endif - for (GSList * node = windows; node; node = node->next) + for (DockWindow & dw : windows) { - DockWindow * dw = (DockWindow *) node->data; - if (! dw->docked) + if (! dw.docked) continue; - for (GSList * node2 = windows; node2; node2 = node2->next) + for (DockWindow & dw2 : windows) { - DockWindow * dw2 = (DockWindow *) node2->data; - if (dw2->docked) + if (dw2.docked) continue; - hori = least_abs (hori, * dw2->x - * dw->x); - hori = least_abs (hori, * dw2->x - (* dw->x + dw->w)); - hori = least_abs (hori, (* dw2->x + dw2->w) - * dw->x); - hori = least_abs (hori, (* dw2->x + dw2->w) - (* dw->x + dw->w)); - vert = least_abs (vert, * dw2->y - * dw->y); - vert = least_abs (vert, * dw2->y - (* dw->y + dw->h)); - vert = least_abs (vert, (* dw2->y + dw2->h) - * dw->y); - vert = least_abs (vert, (* dw2->y + dw2->h) - (* dw->y + dw->h)); + hori = least_abs (hori, * dw2.x - * dw.x); + hori = least_abs (hori, * dw2.x - (* dw.x + dw.w)); + hori = least_abs (hori, (* dw2.x + dw2.w) - * dw.x); + hori = least_abs (hori, (* dw2.x + dw2.w) - (* dw.x + dw.w)); + vert = least_abs (vert, * dw2.y - * dw.y); + vert = least_abs (vert, * dw2.y - (* dw.y + dw.h)); + vert = least_abs (vert, (* dw2.y + dw2.h) - * dw.y); + vert = least_abs (vert, (* dw2.y + dw2.h) - (* dw.y + dw.h)); } } @@ -358,14 +319,13 @@ void dock_move (int x, int y) if (abs (vert) > SNAP_DISTANCE) vert = 0; - for (GSList * node = windows; node; node = node->next) + for (DockWindow & dw : windows) { - DockWindow * dw = (DockWindow *) node->data; - if (! dw->docked) + if (! dw.docked) continue; - * dw->x += hori; - * dw->y += vert; + * dw.x += hori; + * dw.y += vert; } last_x += hori; @@ -373,12 +333,26 @@ void dock_move (int x, int y) /* 5. Really move the windows. */ - for (GSList * node = windows; node; node = node->next) + for (DockWindow & dw : windows) { - DockWindow * dw = (DockWindow *) node->data; - if (! dw->docked) - continue; + if (dw.docked && dw.window) + dw.window->move (* dw.x, * dw.y); + } +} + +void dock_change_scale (int old_scale, int new_scale) +{ + DockWindow & main = windows[WINDOW_MAIN]; - gtk_window_move ((GtkWindow *) dw->window, * dw->x, * dw->y); + for (DockWindow & dw : windows) + { + dw.w = dw.w * new_scale / old_scale; + dw.h = dw.h * new_scale / old_scale; + + if (& dw != & main) + { + * dw.x = * main.x + (* dw.x - * main.x) * new_scale / old_scale; + * dw.y = * main.y + (* dw.y - * main.y) * new_scale / old_scale; + } } } diff --git a/src/skins-qt/drag-handle.cc b/src/skins-qt/drag-handle.cc new file mode 100644 index 0000000..4c7f291 --- /dev/null +++ b/src/skins-qt/drag-handle.cc @@ -0,0 +1,66 @@ +/* + * drag-handle.c + * Copyright 2011 John Lindgren + * + * This file is part of Audacious. + * + * Audacious 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, version 2 or version 3 of the License. + * + * Audacious 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 + * Audacious. If not, see <http://www.gnu.org/licenses/>. + * + * The Audacious team does not consider modular code linking to Audacious or + * using our public API to be a derived work. + */ + +#include "drag-handle.h" +#include "skins_cfg.h" + +bool DragHandle::button_press (QMouseEvent * event) +{ + if (event->button () != Qt::LeftButton) + return false; + + m_held = true; + m_x_origin = event->globalX (); + m_y_origin = event->globalY (); + + if (press) + press (); + + return true; +} + +bool DragHandle::button_release (QMouseEvent * event) +{ + if (event->button () != Qt::LeftButton) + return false; + + m_held = false; + return true; +} + +bool DragHandle::motion (QMouseEvent * event) +{ + if (! m_held) + return true; + + if (drag) + drag ((event->globalX () - m_x_origin) / config.scale, + (event->globalY () - m_y_origin) / config.scale); + + return true; +} + +DragHandle::DragHandle (int w, int h, void (* press) (), void (* drag) (int x, int y)) : + press (press), drag (drag) +{ + set_scale (config.scale); + add_input (w, h, true, false); +} diff --git a/src/skins/ui_dock.h b/src/skins-qt/drag-handle.h index da9c7b6..72bd9a2 100644 --- a/src/skins/ui_dock.h +++ b/src/skins-qt/drag-handle.h @@ -1,5 +1,5 @@ /* - * ui_dock.h + * drag-handle.h * Copyright 2011 John Lindgren * * This file is part of Audacious. @@ -19,18 +19,26 @@ * using our public API to be a derived work. */ -#ifndef SKINS_UI_DOCK_H -#define SKINS_UI_DOCK_H +#ifndef SKINS_DRAG_HANDLE_H +#define SKINS_DRAG_HANDLE_H -#include <gtk/gtk.h> +#include "widget.h" -void dock_add_window (GtkWidget * window, int * x, int * y, int w, int h, - gboolean main); -void dock_remove_window (GtkWidget * window); +class DragHandle : public Widget +{ +public: + DragHandle (int w, int h, void (* press) (), void (* drag) (int x, int y)); -void dock_set_size (GtkWidget * window, int w, int h); +private: + bool button_press (QMouseEvent * event); + bool button_release (QMouseEvent * event); + bool motion (QMouseEvent * event); -void dock_move_start (GtkWidget * window, int x, int y); -void dock_move (int x, int y); + void (* press) (); + void (* drag) (int x_offset, int y_offset); + + bool m_held = false; + int m_x_origin = 0, m_y_origin = 0; +}; #endif diff --git a/src/skins-qt/eq-graph.cc b/src/skins-qt/eq-graph.cc new file mode 100644 index 0000000..cc3af58 --- /dev/null +++ b/src/skins-qt/eq-graph.cc @@ -0,0 +1,135 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2011 John Lindgren + * + * Based on: + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + */ + +#include <libaudcore/equalizer.h> +#include <libaudcore/runtime.h> + +#include "skins_cfg.h" +#include "skin.h" +#include "eq-graph.h" + +#define N 10 +static_assert (N == AUD_EQ_NBANDS, "only a 10-band EQ is supported"); + +static void init_spline (const double * x, const double * y, double * y2) +{ + int k; + double p, qn, sig, un; + double u[N]; + + y2[0] = u[0] = 0.0; + + for (int i = 1; i < N - 1; i ++) + { + sig = ((double) x[i] - x[i - 1]) / ((double) x[i + 1] - x[i - 1]); + p = sig * y2[i - 1] + 2.0; + y2[i] = (sig - 1.0) / p; + u[i] = + (((double) y[i + 1] - y[i]) / (x[i + 1] - x[i])) - + (((double) y[i] - y[i - 1]) / (x[i] - x[i - 1])); + u[i] = (6.0 * u[i] / (x[i + 1] - x[i - 1]) - sig * u[i - 1]) / p; + } + qn = un = 0.0; + + y2[N - 1] = (un - qn * u[N - 2]) / (qn * y2[N - 2] + 1.0); + for (k = N - 2; k >= 0; k --) + y2[k] = y2[k] * y2[k + 1] + u[k]; +} + +static double eval_spline (const double * xa, const double * ya, const double * y2a, double x) +{ + int klo, khi, k; + double h, b, a; + + klo = 0; + khi = N - 1; + while (khi - klo > 1) + { + k = (khi + klo) >> 1; + if (xa[k] > x) + khi = k; + else + klo = k; + } + h = xa[khi] - xa[klo]; + a = (xa[khi] - x) / h; + b = (x - xa[klo]) / h; + return (a * ya[klo] + b * ya[khi] + + ((a * a * a - a) * y2a[klo] + + (b * b * b - b) * y2a[khi]) * (h * h) / 6.0); +} + +void EqGraph::draw (QPainter & cr) +{ + static const double x[N] = {0, 11, 23, 35, 47, 59, 71, 83, 97, 109}; + + if (skin.pixmaps[SKIN_EQMAIN].height () < 313) + return; + + skin_draw_pixbuf (cr, SKIN_EQMAIN, 0, 294, 0, 0, 113, 19); + skin_draw_pixbuf (cr, SKIN_EQMAIN, 0, 314, 0, 9 + (aud_get_double (nullptr, + "equalizer_preamp") * 9 + AUD_EQ_MAX_GAIN / 2) / AUD_EQ_MAX_GAIN, 113, 1); + + double bands[N]; + aud_eq_get_bands (bands); + + double yf[N]; + init_spline (x, bands, yf); + + int py = 0; + for (int i = 0; i < 109; i ++) + { + int y = 9.5 - eval_spline (x, bands, yf, i) * 9 / AUD_EQ_MAX_GAIN; + y = aud::clamp (y, 0, 18); + + if (!i) + py = y; + + int ymin, ymax; + + if (y > py) + { + ymin = py + 1; + ymax = y; + } + else if (y < py) + { + ymin = y; + ymax = py - 1; + } + else + ymin = ymax = y; + + py = y; + + for (y = ymin; y <= ymax; y ++) + cr.fillRect (i + 2, y, 1, 1, QColor (skin.eq_spline_colors[y])); + } +} + +EqGraph::EqGraph () +{ + set_scale (config.scale); + add_drawable (113, 19); +} diff --git a/src/skins/ui_skinned_playlist_slider.h b/src/skins-qt/eq-graph.h index 8d28d3e..0ac2282 100644 --- a/src/skins/ui_skinned_playlist_slider.h +++ b/src/skins-qt/eq-graph.h @@ -25,13 +25,19 @@ * Audacious or using our public API to be a derived work. */ -#ifndef SKINS_UI_SKINNED_PLAYLIST_SLIDER_H -#define SKINS_UI_SKINNED_PLAYLIST_SLIDER_H +#ifndef SKINS_UI_SKINNED_EQUALIZER_GRAPH_H +#define SKINS_UI_SKINNED_EQUALIZER_GRAPH_H -#include <gtk/gtk.h> +#include "widget.h" -GtkWidget * ui_skinned_playlist_slider_new (GtkWidget * list, int height); -void ui_skinned_playlist_slider_resize (GtkWidget * slider, int height); -void ui_skinned_playlist_slider_update (GtkWidget * slider); +class EqGraph : public Widget +{ +public: + EqGraph (); + void refresh () { queue_draw (); } + +private: + void draw (QPainter & cr); +}; #endif diff --git a/src/skins-qt/eq-slider.cc b/src/skins-qt/eq-slider.cc new file mode 100644 index 0000000..57d3d62 --- /dev/null +++ b/src/skins-qt/eq-slider.cc @@ -0,0 +1,124 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2011 John Lindgren + * + * Based on: + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + */ + +#include <libaudcore/audstrings.h> +#include <libaudcore/equalizer.h> +#include <libaudcore/i18n.h> +#include <libaudcore/runtime.h> + +#include "skins_cfg.h" +#include "main.h" +#include "skin.h" +#include "eq-slider.h" + +void EqSlider::draw (QPainter & cr) +{ + int frame = 27 - m_pos * 27 / 50; + if (frame < 14) + skin_draw_pixbuf (cr, SKIN_EQMAIN, 13 + 15 * frame, 164, 0, 0, 14, 63); + else + skin_draw_pixbuf (cr, SKIN_EQMAIN, 13 + 15 * (frame - 14), 229, 0, 0, 14, 63); + + if (m_pressed) + skin_draw_pixbuf (cr, SKIN_EQMAIN, 0, 176, 1, m_pos, 11, 11); + else + skin_draw_pixbuf (cr, SKIN_EQMAIN, 0, 164, 1, m_pos, 11, 11); +} + +void EqSlider::moved (int pos) +{ + m_pos = aud::clamp (pos, 0, 50); + if (m_pos == 24 || m_pos == 26) + m_pos = 25; + + m_value = (float) (25 - m_pos) * AUD_EQ_MAX_GAIN / 25; + + if (m_band < 0) + aud_set_double (nullptr, "equalizer_preamp", m_value); + else + aud_eq_set_band (m_band, m_value); + + mainwin_show_status_message (str_printf ("%s: %+.1f dB", (const char *) m_name, m_value)); +} + +bool EqSlider::button_press (QMouseEvent * event) +{ + if (event->button () != Qt::LeftButton) + return false; + + m_pressed = true; + moved (event->y () / config.scale - 5); + queue_draw (); + return true; +} + +bool EqSlider::button_release (QMouseEvent * event) +{ + if (event->button () != Qt::LeftButton) + return false; + + if (! m_pressed) + return true; + + m_pressed = false; + moved (event->y () / config.scale - 5); + queue_draw (); + return true; +} + +bool EqSlider::motion (QMouseEvent * event) +{ + if (! m_pressed) + return true; + + moved (event->y () / config.scale - 5); + queue_draw (); + return true; +} + +bool EqSlider::scroll (QWheelEvent * event) +{ + int delta = event->angleDelta ().y () / 60; + moved (m_pos - delta); + queue_draw (); + return true; +} + +void EqSlider::set_value (float value) +{ + if (m_pressed) + return; + + m_value = value; + m_pos = aud::clamp (25 - (int) (value * 25 / AUD_EQ_MAX_GAIN), 0, 50); + queue_draw (); +} + +EqSlider::EqSlider (const char * name, int band) : + m_name (name), + m_band (band) +{ + set_scale (config.scale); + add_input (14, 63, true, true); +} diff --git a/src/skins/ui_skinned_equalizer_slider.h b/src/skins-qt/eq-slider.h index bca392a..f8ccef8 100644 --- a/src/skins/ui_skinned_equalizer_slider.h +++ b/src/skins-qt/eq-slider.h @@ -25,10 +25,31 @@ #ifndef SKINS_UI_SKINNED_EQUALIZER_SLIDER_H #define SKINS_UI_SKINNED_EQUALIZER_SLIDER_H -#include <gtk/gtk.h> +#include <libaudcore/objects.h> -GtkWidget * eq_slider_new (const char * name); -void eq_slider_set_val (GtkWidget * widget, float val); -float eq_slider_get_val (GtkWidget * widget); +#include "widget.h" + +class EqSlider : public Widget +{ +public: + EqSlider (const char * name, int band); + void set_value (float value); + +private: + void draw (QPainter & cr); + bool button_press (QMouseEvent * event); + bool button_release (QMouseEvent * event); + bool scroll (QWheelEvent * event); + bool motion (QMouseEvent * event); + + void moved (int pos); + + String m_name; + int m_band; + + int m_pos = 0; + float m_value = 0; + bool m_pressed = false; +}; #endif diff --git a/src/skins-qt/equalizer.cc b/src/skins-qt/equalizer.cc new file mode 100644 index 0000000..8e02a45 --- /dev/null +++ b/src/skins-qt/equalizer.cc @@ -0,0 +1,285 @@ +/* Audacious - Cross-platform multimedia player + * Copyright (C) 2005-2014 Audacious development team. + * + * Based on BMP: + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include <string.h> + +#include <libaudcore/audstrings.h> +#include <libaudcore/drct.h> +#include <libaudcore/equalizer.h> +#include <libaudcore/hook.h> +#include <libaudcore/i18n.h> +#include <libaudcore/runtime.h> + +#include "menus.h" +#include "plugin.h" +#include "skins_cfg.h" +#include "equalizer.h" +#include "main.h" +#include "button.h" +#include "eq-graph.h" +#include "eq-slider.h" +#include "hslider.h" +#include "window.h" +#include "util.h" +#include "view.h" + +class EqWindow : public Window +{ +public: + EqWindow (bool shaded) : + Window (WINDOW_EQ, & config.equalizer_x, & config.equalizer_y, 275, + shaded ? 14 : 116, shaded) {} + +private: + void draw (QPainter & cr); + bool button_press (QMouseEvent * event); +}; + +Window * equalizerwin; + +static EqGraph * equalizerwin_graph; +static Button * equalizerwin_on, * equalizerwin_auto; +static Button * equalizerwin_close, * equalizerwin_shade; +static Button * equalizerwin_shaded_close, * equalizerwin_shaded_shade; +static Button * equalizerwin_presets; +static EqSlider * equalizerwin_preamp, * equalizerwin_bands[10]; +static HSlider * equalizerwin_volume, * equalizerwin_balance; + +static void equalizerwin_shade_toggle () +{ + view_set_equalizer_shaded (! aud_get_bool ("skins", "equalizer_shaded")); +} + +static void eq_on_cb (Button * button, QMouseEvent * event) +{ + aud_set_bool (nullptr, "equalizer_active", button->get_active ()); +} + +static void update_from_config (void *, void *) +{ + equalizerwin_on->set_active (aud_get_bool (nullptr, "equalizer_active")); + equalizerwin_preamp->set_value (aud_get_double (nullptr, "equalizer_preamp")); + + double bands[AUD_EQ_NBANDS]; + aud_eq_get_bands (bands); + + for (int i = 0; i < AUD_EQ_NBANDS; i ++) + equalizerwin_bands[i]->set_value (bands[i]); + + equalizerwin_graph->refresh (); +} + +bool EqWindow::button_press (QMouseEvent * event) +{ + if (event->button () == Qt::LeftButton && + event->type () == QEvent::MouseButtonDblClick && + event->y () < 14 * config.scale) + { + equalizerwin_shade_toggle (); + return true; + } + + if (event->button () == Qt::RightButton && event->type () == QEvent::MouseButtonPress) + { + menu_popup (UI_MENU_MAIN, event->globalX (), event->globalY (), false, false); + return true; + } + + return Window::button_press (event); +} + +static void equalizerwin_close_cb () +{ + view_set_show_equalizer (false); +} + +static void eqwin_volume_set_knob () +{ + int pos = equalizerwin_volume->get_pos (); + int x = (pos < 32) ? 1 : (pos < 63) ? 4 : 7; + equalizerwin_volume->set_knob (x, 30, x, 30); +} + +void equalizerwin_set_volume_slider (int percent) +{ + equalizerwin_volume->set_pos ((percent * 94 + 50) / 100); + eqwin_volume_set_knob (); +} + +static void eqwin_volume_motion_cb () +{ + eqwin_volume_set_knob (); + int pos = equalizerwin_volume->get_pos (); + int v = (pos * 100 + 47) / 94; + + mainwin_adjust_volume_motion (v); + mainwin_set_volume_slider (v); +} + +static void eqwin_volume_release_cb () +{ + eqwin_volume_set_knob (); + mainwin_adjust_volume_release (); +} + +static void eqwin_balance_set_knob () +{ + int pos = equalizerwin_balance->get_pos (); + int x = (pos < 13) ? 11 : (pos < 26) ? 14 : 17; + equalizerwin_balance->set_knob (x, 30, x, 30); +} + +void equalizerwin_set_balance_slider (int percent) +{ + if (percent > 0) + equalizerwin_balance->set_pos (19 + (percent * 19 + 50) / 100); + else + equalizerwin_balance->set_pos (19 + (percent * 19 - 50) / 100); + + eqwin_balance_set_knob (); +} + +static void eqwin_balance_motion_cb () +{ + eqwin_balance_set_knob (); + int pos = equalizerwin_balance->get_pos (); + pos = aud::min(pos, 38); /* The skin uses a even number of pixels + for the balance-slider *sigh* */ + int b; + if (pos > 19) + b = ((pos - 19) * 100 + 9) / 19; + else + b = ((pos - 19) * 100 - 9) / 19; + + mainwin_adjust_balance_motion (b); + mainwin_set_balance_slider (b); +} + +static void eqwin_balance_release_cb () +{ + eqwin_balance_set_knob (); + mainwin_adjust_balance_release (); +} + +static void equalizerwin_create_widgets () +{ + equalizerwin_on = new Button (25, 12, 10, 119, 128, 119, 69, 119, 187, 119, SKIN_EQMAIN, SKIN_EQMAIN); + equalizerwin->put_widget (false, equalizerwin_on, 14, 18); + equalizerwin_on->set_active (aud_get_bool (nullptr, "equalizer_active")); + equalizerwin_on->on_release (eq_on_cb); + + // AUTO button currently does nothing + equalizerwin_auto = new Button (33, 12, 35, 119, 153, 119, 94, 119, 212, 119, SKIN_EQMAIN, SKIN_EQMAIN); + equalizerwin->put_widget (false, equalizerwin_auto, 39, 18); + + equalizerwin_presets = new Button (44, 12, 224, 164, 224, 176, SKIN_EQMAIN, SKIN_EQMAIN); + equalizerwin->put_widget (false, equalizerwin_presets, 217, 18); +// equalizerwin_presets->on_release ((ButtonCB) audgui_show_eq_preset_window); + + equalizerwin_close = new Button (9, 9, 0, 116, 0, 125, SKIN_EQMAIN, SKIN_EQMAIN); + equalizerwin->put_widget (false, equalizerwin_close, 264, 3); + equalizerwin_close->on_release ((ButtonCB) equalizerwin_close_cb); + + equalizerwin_shade = new Button (9, 9, 254, 137, 1, 38, SKIN_EQMAIN, SKIN_EQ_EX); + equalizerwin->put_widget (false, equalizerwin_shade, 254, 3); + equalizerwin_shade->on_release ((ButtonCB) equalizerwin_shade_toggle); + + equalizerwin_shaded_close = new Button (9, 9, 11, 38, 11, 47, SKIN_EQ_EX, SKIN_EQ_EX); + equalizerwin->put_widget (true, equalizerwin_shaded_close, 264, 3); + equalizerwin_shaded_close->on_release ((ButtonCB) equalizerwin_close_cb); + + equalizerwin_shaded_shade = new Button (9, 9, 254, 3, 1, 47, SKIN_EQ_EX, SKIN_EQ_EX); + equalizerwin->put_widget (true, equalizerwin_shaded_shade, 254, 3); + equalizerwin_shaded_shade->on_release ((ButtonCB) equalizerwin_shade_toggle); + + equalizerwin_graph = new EqGraph; + equalizerwin->put_widget (false, equalizerwin_graph, 86, 17); + + equalizerwin_preamp = new EqSlider (_("Preamp"), -1); + equalizerwin->put_widget (false, equalizerwin_preamp, 21, 38); + equalizerwin_preamp->set_value (aud_get_double (nullptr, "equalizer_preamp")); + + const char * const bandnames[AUD_EQ_NBANDS] = {N_("31 Hz"), + N_("63 Hz"), N_("125 Hz"), N_("250 Hz"), N_("500 Hz"), N_("1 kHz"), + N_("2 kHz"), N_("4 kHz"), N_("8 kHz"), N_("16 kHz")}; + double bands[AUD_EQ_NBANDS]; + aud_eq_get_bands (bands); + + for (int i = 0; i < AUD_EQ_NBANDS; i ++) + { + equalizerwin_bands[i] = new EqSlider (_(bandnames[i]), i); + equalizerwin->put_widget (false, equalizerwin_bands[i], 78 + 18 * i, 38); + equalizerwin_bands[i]->set_value (bands[i]); + } + + equalizerwin_volume = new HSlider (0, 94, SKIN_EQ_EX, 97, 8, 61, 4, 3, 7, 1, 30, 1, 30); + equalizerwin->put_widget (true, equalizerwin_volume, 61, 4); + equalizerwin_volume->on_move (eqwin_volume_motion_cb); + equalizerwin_volume->on_release (eqwin_volume_release_cb); + + equalizerwin_balance = new HSlider (0, 39, SKIN_EQ_EX, 42, 8, 164, 4, 3, 7, 11, 30, 11, 30); + equalizerwin->put_widget (true, equalizerwin_balance, 164, 4); + equalizerwin_balance->on_move (eqwin_balance_motion_cb); + equalizerwin_balance->on_release (eqwin_balance_release_cb); +} + +void EqWindow::draw (QPainter & cr) +{ + skin_draw_pixbuf (cr, SKIN_EQMAIN, 0, 0, 0, 0, 275, is_shaded () ? 14 : 116); + + if (is_shaded ()) + skin_draw_pixbuf (cr, SKIN_EQ_EX, 0, 0, 0, 0, 275, 14); + else + skin_draw_pixbuf (cr, SKIN_EQMAIN, 0, 134, 0, 0, 275, 14); +} + +static void equalizerwin_create_window () +{ + bool shaded = aud_get_bool ("skins", "equalizer_shaded"); + + /* do not allow shading the equalizer if eq_ex.bmp is missing */ + if (skin.pixmaps[SKIN_EQ_EX].isNull ()) + shaded = false; + + equalizerwin = new EqWindow (shaded); + equalizerwin->setWindowTitle (_("Audacious Equalizer")); +} + +void equalizerwin_unhook () +{ + hook_dissociate ("set equalizer_active", (HookFunction) update_from_config); + hook_dissociate ("set equalizer_bands", (HookFunction) update_from_config); + hook_dissociate ("set equalizer_preamp", (HookFunction) update_from_config); +} + +void equalizerwin_create () +{ + equalizerwin_create_window (); + equalizerwin_create_widgets (); + + hook_associate ("set equalizer_active", (HookFunction) update_from_config, nullptr); + hook_associate ("set equalizer_bands", (HookFunction) update_from_config, nullptr); + hook_associate ("set equalizer_preamp", (HookFunction) update_from_config, nullptr); +} diff --git a/src/skins/ui_equalizer.h b/src/skins-qt/equalizer.h index 07b40e5..e2047f4 100644 --- a/src/skins/ui_equalizer.h +++ b/src/skins-qt/equalizer.h @@ -26,29 +26,13 @@ #ifndef SKINS_UI_EQUALIZER_H #define SKINS_UI_EQUALIZER_H -#include <gtk/gtk.h> +class Window; -#include <libaudcore/equalizer.h> +void equalizerwin_create (); +void equalizerwin_unhook (); +void equalizerwin_set_volume_slider (int percent); +void equalizerwin_set_balance_slider (int percent); -#define EQUALIZER_DEFAULT_DIR_PRESET "dir_default.preset" -#define EQUALIZER_DEFAULT_PRESET_EXT "preset" - -void equalizerwin_create(void); -void equalizerwin_set_volume_slider(int percent); -void equalizerwin_set_balance_slider(int percent); -void equalizerwin_eq_changed(void); - -void equalizerwin_apply_preset (const EqualizerPreset & preset); -void equalizerwin_update_preset (EqualizerPreset & preset); -void equalizerwin_import_presets (Index<EqualizerPreset> && presets); - -extern GtkWidget *equalizerwin; -extern GtkWidget *equalizerwin_graph; - -extern Index<EqualizerPreset> equalizer_presets, equalizer_auto_presets; - -gboolean equalizerwin_load_preset (Index<EqualizerPreset> & list, const char * name); -void equalizerwin_save_preset (Index<EqualizerPreset> & list, const char * name, const char * filename); -void equalizerwin_delete_preset (Index<EqualizerPreset> & list, const char * name, const char * filename); +extern Window * equalizerwin; #endif /* SKINS_UI_EQUALIZER_H */ diff --git a/src/skins-qt/hslider.cc b/src/skins-qt/hslider.cc new file mode 100644 index 0000000..0cb2c1c --- /dev/null +++ b/src/skins-qt/hslider.cc @@ -0,0 +1,129 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2011 John Lindgren + * + * Based on: + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include <libaudcore/objects.h> + +#include "skins_cfg.h" +#include "hslider.h" + +void HSlider::draw (QPainter & cr) +{ + skin_draw_pixbuf (cr, m_si, m_fx, m_fy, 0, 0, m_w, m_h); + + if (m_pressed) + skin_draw_pixbuf (cr, m_si, m_kpx, m_kpy, m_pos, (m_h - m_kh) / 2, m_kw, m_kh); + else + skin_draw_pixbuf (cr, m_si, m_knx, m_kny, m_pos, (m_h - m_kh) / 2, m_kw, m_kh); +} + +bool HSlider::button_press (QMouseEvent * event) +{ + if (event->button () != Qt::LeftButton) + return false; + + m_pressed = true; + m_pos = aud::clamp ((int) event->x () / config.scale - m_kw / 2, m_min, m_max); + + if (move) + move (); + + queue_draw (); + return true; +} + +bool HSlider::button_release (QMouseEvent * event) +{ + if (event->button () != Qt::LeftButton) + return false; + + if (! m_pressed) + return true; + + m_pressed = false; + m_pos = aud::clamp ((int) event->x () / config.scale - m_kw / 2, m_min, m_max); + + if (release) + release (); + + queue_draw (); + return true; +} + +bool HSlider::motion (QMouseEvent * event) +{ + if (! m_pressed) + return true; + + m_pressed = true; + m_pos = aud::clamp ((int) event->x () / config.scale - m_kw / 2, m_min, m_max); + + if (move) + move (); + + queue_draw (); + return true; +} + +HSlider::HSlider (int min, int max, SkinPixmapId si, int w, int h, int fx, + int fy, int kw, int kh, int knx, int kny, int kpx, int kpy) : + m_min (min), m_max (max), m_si (si), m_w (w), m_h (h), m_fx (fx), m_fy (fy), + m_kw (kw), m_kh (kh), m_knx (knx), m_kny (kny), m_kpx (kpx), m_kpy (kpy) +{ + set_scale (config.scale); + add_input (w, h, true, true); +} + +void HSlider::set_frame (int fx, int fy) +{ + m_fx = fx; + m_fy = fy; + queue_draw (); +} + +void HSlider::set_knob (int knx, int kny, int kpx, int kpy) +{ + m_knx = knx; + m_kny = kny; + m_kpx = kpx; + m_kpy = kpy; + queue_draw (); +} + +void HSlider::set_pos (int pos) +{ + if (m_pressed) + return; + + m_pos = aud::clamp (pos, m_min, m_max); + queue_draw (); +} + +void HSlider::set_pressed (bool pressed) +{ + m_pressed = pressed; + queue_draw (); +} diff --git a/src/skins-qt/hslider.h b/src/skins-qt/hslider.h new file mode 100644 index 0000000..adb4174 --- /dev/null +++ b/src/skins-qt/hslider.h @@ -0,0 +1,70 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2011 John Lindgren + * + * Based on: + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#ifndef SKINS_UI_SKINNED_HORIZONTAL_SLIDER_H +#define SKINS_UI_SKINNED_HORIZONTAL_SLIDER_H + +#include "widget.h" +#include "skin.h" + +class HSlider : public Widget +{ +public: + HSlider (int min, int max, SkinPixmapId si, int w, int h, int fx, int fy, + int kw, int kh, int knx, int kny, int kpx, int kpy); + + void set_frame (int fx, int fy); + void set_knob (int knx, int kny, int kpx, int kpy); + int get_pos () { return m_pos; } + void set_pos (int pos); + bool get_pressed () { return m_pressed; } + void set_pressed (bool pressed); + + void on_move (void (* callback) ()) { move = callback; } + void on_release (void (* callback) ()) { release = callback; } + +private: + void draw (QPainter & cr); + bool button_press (QMouseEvent * event); + bool button_release (QMouseEvent * event); + bool motion (QMouseEvent * event); + + int m_min, m_max; + SkinPixmapId m_si; + int m_w, m_h; + int m_fx, m_fy; + int m_kw, m_kh; + int m_knx, m_kny, m_kpx, m_kpy; + + int m_pos = 0; + bool m_pressed = false; + + void (* move) () = nullptr; + void (* release) () = nullptr; +}; + +#endif diff --git a/src/skins-qt/main.cc b/src/skins-qt/main.cc new file mode 100644 index 0000000..63eb7ee --- /dev/null +++ b/src/skins-qt/main.cc @@ -0,0 +1,1185 @@ +/* Audacious - Cross-platform multimedia player + * Copyright (C) 2005-2011 Audacious development team. + * + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include <math.h> +#include <stdlib.h> +#include <string.h> +#include <sys/time.h> + +#include <libaudcore/audstrings.h> +#include <libaudcore/drct.h> +#include <libaudcore/hook.h> +#include <libaudcore/i18n.h> +#include <libaudcore/mainloop.h> +#include <libaudcore/plugins.h> +#include <libaudcore/runtime.h> +#include <libaudqt/libaudqt.h> + +#include "actions-mainwin.h" +#include "actions-playlist.h" +#include "dnd.h" +#include "menus.h" +#include "plugin.h" +#include "skins_cfg.h" +#include "equalizer.h" +#include "main.h" +#include "vis-callbacks.h" +#include "playlist.h" +#include "button.h" +#include "hslider.h" +#include "menurow.h" +#include "monostereo.h" +#include "number.h" +#include "playlist-widget.h" +#include "playstatus.h" +#include "textbox.h" +#include "window.h" +#include "vis.h" +#include "util.h" +#include "view.h" + +#define SEEK_THRESHOLD 200 /* milliseconds */ +#define SEEK_SPEED 50 /* milliseconds per pixel */ + +class MainWindow : public Window +{ +public: + MainWindow (bool shaded) : + Window (WINDOW_MAIN, & config.player_x, & config.player_y, + shaded ? MAINWIN_SHADED_WIDTH : skin.hints.mainwin_width, + shaded ? MAINWIN_SHADED_HEIGHT : skin.hints.mainwin_height, shaded) {} + +private: + void draw (QPainter & cr); + bool button_press (QMouseEvent * event); + bool scroll (QWheelEvent * event); +}; + +Window * mainwin; + +Button * mainwin_eq, * mainwin_pl; +TextBox * mainwin_info; +MenuRow * mainwin_menurow; + +SkinnedVis * mainwin_vis; +SmallVis * mainwin_svis; + +static bool seeking = false; +static int seek_start, seek_time; + +static TextBox * locked_textbox = nullptr; +static String locked_old_text; + +static QueuedFunc status_message_timeout; +static QueuedFunc mainwin_volume_release_timeout; + +static Button * mainwin_menubtn, * mainwin_minimize, * mainwin_shade, * mainwin_close; +static Button * mainwin_shaded_menubtn, * mainwin_shaded_minimize, * mainwin_shaded_shade, * mainwin_shaded_close; + +static Button * mainwin_rew, * mainwin_fwd; +static Button * mainwin_eject; +static Button * mainwin_play, * mainwin_pause, * mainwin_stop; +static Button * mainwin_shuffle, * mainwin_repeat; + +static TextBox * mainwin_stime_min, * mainwin_stime_sec; +static TextBox * mainwin_rate_text, * mainwin_freq_text, * mainwin_othertext; + +static PlayStatus * mainwin_playstatus; +static SkinnedNumber * mainwin_minus_num, * mainwin_10min_num, * mainwin_min_num; +static SkinnedNumber * mainwin_10sec_num, * mainwin_sec_num; +static HSlider * mainwin_position, * mainwin_sposition; + +static HSlider * mainwin_volume, * mainwin_balance; +static MonoStereo * mainwin_monostereo; + +static Button * mainwin_srew, * mainwin_splay, * mainwin_spause; +static Button * mainwin_sstop, * mainwin_sfwd, * mainwin_seject, * mainwin_about; + +static void mainwin_position_motion_cb (); +static void mainwin_position_release_cb (); +static void seek_timeout (void * rewind); + +static void format_time (char buf[7], int time, int length) +{ + bool zero = aud_get_bool (nullptr, "leading_zero"); + bool remaining = aud_get_bool ("skins", "show_remaining_time"); + + if (remaining && length > 0) + { + time = (length - time) / 1000; + + if (time < 60) + snprintf (buf, 7, zero ? "-00:%02d" : " -0:%02d", time); + else if (time < 6000) + snprintf (buf, 7, zero ? "%03d:%02d" : "%3d:%02d", -time / 60, time % 60); + else + snprintf (buf, 7, "%3d:%02d", -time / 3600, time / 60 % 60); + } + else + { + time /= 1000; + + if (time < 6000) + snprintf (buf, 7, zero ? " %02d:%02d" : " %2d:%02d", time / 60, time % 60); + else if (time < 60000) + snprintf (buf, 7, "%3d:%02d", time / 60, time % 60); + else + snprintf (buf, 7, "%3d:%02d", time / 3600, time / 60 % 60); + } +} + +static void mainwin_menubtn_cb () +{ + int x, y; + mainwin->getPosition (& x, & y); + menu_popup (UI_MENU_MAIN, x + 6 * config.scale, + y + MAINWIN_SHADED_HEIGHT * config.scale, false, false); +} + +static void mainwin_minimize_cb () +{ + mainwin->showMinimized (); +} + +static void mainwin_shade_toggle () +{ + view_set_player_shaded (! aud_get_bool ("skins", "player_shaded")); +} + +static void mainwin_lock_info_text (const char * text) +{ + if (! locked_textbox) + { + locked_textbox = skin.hints.mainwin_othertext_is_status ? mainwin_othertext : mainwin_info; + locked_old_text = locked_textbox->get_text (); + } + + locked_textbox->set_text (text); +} + +static void mainwin_release_info_text (void * = nullptr) +{ + if (locked_textbox) + { + locked_textbox->set_text (locked_old_text); + locked_textbox = nullptr; + locked_old_text = String (); + } +} + +static void set_info_text (TextBox * textbox, const char * text) +{ + if (textbox == locked_textbox) + locked_old_text = String (text); + else + textbox->set_text (text); +} + +#define mainwin_set_info_text(t) set_info_text (mainwin_info, (t)) +#define mainwin_set_othertext(t) set_info_text (mainwin_othertext, (t)) + +void mainwin_show_status_message (const char * message) +{ + mainwin_lock_info_text (message); + status_message_timeout.queue (1000, mainwin_release_info_text, nullptr); +} + +static void mainwin_set_song_title (const char * title) +{ + if (title) + mainwin->setWindowTitle ((const char *) str_printf (_("%s - Audacious"), title)); + else + mainwin->setWindowTitle (_("Audacious")); + + mainwin_set_info_text (title ? title : ""); +} + +static void title_change () +{ + if (aud_drct_get_ready ()) + mainwin_set_song_title (aud_drct_get_title ()); + else + mainwin_set_song_title ("Buffering ..."); +} + +static void setup_widget (Widget * widget, int x, int y, bool show) +{ + widget->setVisible (show); + mainwin->move_widget (false, widget, x, y); +} + +void mainwin_refresh_hints () +{ + const SkinHints * p = & skin.hints; + + mainwin_menurow->setVisible (p->mainwin_menurow_visible); + mainwin_rate_text->setVisible (p->mainwin_streaminfo_visible); + mainwin_freq_text->setVisible (p->mainwin_streaminfo_visible); + mainwin_monostereo->setVisible (p->mainwin_streaminfo_visible); + + mainwin_info->set_width (p->mainwin_text_width); + + setup_widget (mainwin_vis, p->mainwin_vis_x, p->mainwin_vis_y, p->mainwin_vis_visible); + setup_widget (mainwin_info, p->mainwin_text_x, p->mainwin_text_y, p->mainwin_text_visible); + setup_widget (mainwin_othertext, p->mainwin_infobar_x, p->mainwin_infobar_y, p->mainwin_othertext_visible); + + bool playing = aud_drct_get_playing (); + bool can_seek = aud_drct_get_length () > 0; + + setup_widget (mainwin_minus_num, p->mainwin_number_0_x, p->mainwin_number_0_y, playing); + setup_widget (mainwin_10min_num, p->mainwin_number_1_x, p->mainwin_number_1_y, playing); + setup_widget (mainwin_min_num, p->mainwin_number_2_x, p->mainwin_number_2_y, playing); + setup_widget (mainwin_10sec_num, p->mainwin_number_3_x, p->mainwin_number_3_y, playing); + setup_widget (mainwin_sec_num, p->mainwin_number_4_x, p->mainwin_number_4_y, playing); + setup_widget (mainwin_position, p->mainwin_position_x, p->mainwin_position_y, can_seek); + + setup_widget (mainwin_playstatus, p->mainwin_playstatus_x, p->mainwin_playstatus_y, true); + setup_widget (mainwin_volume, p->mainwin_volume_x, p->mainwin_volume_y, true); + setup_widget (mainwin_balance, p->mainwin_balance_x, p->mainwin_balance_y, true); + setup_widget (mainwin_rew, p->mainwin_previous_x, p->mainwin_previous_y, true); + setup_widget (mainwin_play, p->mainwin_play_x, p->mainwin_play_y, true); + setup_widget (mainwin_pause, p->mainwin_pause_x, p->mainwin_pause_y, true); + setup_widget (mainwin_stop, p->mainwin_stop_x, p->mainwin_stop_y, true); + setup_widget (mainwin_fwd, p->mainwin_next_x, p->mainwin_next_y, true); + setup_widget (mainwin_eject, p->mainwin_eject_x, p->mainwin_eject_y, true); + setup_widget (mainwin_eq, p->mainwin_eqbutton_x, p->mainwin_eqbutton_y, true); + setup_widget (mainwin_pl, p->mainwin_plbutton_x, p->mainwin_plbutton_y, true); + setup_widget (mainwin_shuffle, p->mainwin_shuffle_x, p->mainwin_shuffle_y, true); + setup_widget (mainwin_repeat, p->mainwin_repeat_x, p->mainwin_repeat_y, true); + setup_widget (mainwin_about, p->mainwin_about_x, p->mainwin_about_y, true); + setup_widget (mainwin_minimize, p->mainwin_minimize_x, p->mainwin_minimize_y, true); + setup_widget (mainwin_shade, p->mainwin_shade_x, p->mainwin_shade_y, true); + setup_widget (mainwin_close, p->mainwin_close_x, p->mainwin_close_y, true); + + if (aud_get_bool ("skins", "player_shaded")) + mainwin->resize (MAINWIN_SHADED_WIDTH, MAINWIN_SHADED_HEIGHT); + else + mainwin->resize (p->mainwin_width, p->mainwin_height); + + mainwin_vis->set_colors (); +} + +/* note that the song info is not translated since it is displayed using + * the skinned bitmap font, which supports only the English alphabet */ +static void mainwin_set_song_info (int bitrate, int samplerate, int channels) +{ + char scratch[32]; + int length; + + if (bitrate > 0) + { + if (bitrate < 1000000) + snprintf (scratch, sizeof scratch, "%3d", bitrate / 1000); + else + snprintf (scratch, sizeof scratch, "%2dH", bitrate / 100000); + + mainwin_rate_text->set_text (scratch); + } + else + mainwin_rate_text->set_text (nullptr); + + if (samplerate > 0) + { + snprintf (scratch, sizeof scratch, "%2d", samplerate / 1000); + mainwin_freq_text->set_text (scratch); + } + else + mainwin_freq_text->set_text (nullptr); + + mainwin_monostereo->set_num_channels (channels); + + if (bitrate > 0) + snprintf (scratch, sizeof scratch, "%d kbps", bitrate / 1000); + else + scratch[0] = 0; + + if (samplerate > 0) + { + length = strlen (scratch); + snprintf (scratch + length, sizeof scratch - length, "%s%d kHz", length ? + ", " : "", samplerate / 1000); + } + + if (channels > 0) + { + length = strlen (scratch); + snprintf (scratch + length, sizeof scratch - length, "%s%s", length ? + ", " : "", channels > 2 ? "surround" : channels > 1 ? "stereo" : "mono"); + } + + mainwin_set_othertext (scratch); +} + +static void info_change () +{ + int bitrate, samplerate, channels; + aud_drct_get_info (bitrate, samplerate, channels); + mainwin_set_song_info (bitrate, samplerate, channels); +} + +static void playback_pause () +{ + mainwin_playstatus->set_status (STATUS_PAUSE); +} + +static void playback_unpause () +{ + mainwin_playstatus->set_status (STATUS_PLAY); +} + +void mainwin_playback_begin () +{ + mainwin_update_song_info (); + + mainwin_stime_min->show (); + mainwin_stime_sec->show (); + mainwin_minus_num->show (); + mainwin_10min_num->show (); + mainwin_min_num->show (); + mainwin_10sec_num->show (); + mainwin_sec_num->show (); + + if (aud_drct_get_length () > 0) + { + mainwin_position->show (); + mainwin_sposition->show (); + } + + if (aud_drct_get_paused ()) + playback_pause (); + else + playback_unpause (); + + title_change (); + info_change (); +} + +static void mainwin_playback_stop () +{ + seeking = false; + timer_remove (TimerRate::Hz10, seek_timeout); + + mainwin_set_song_title (nullptr); + + mainwin_vis->clear (); + mainwin_svis->clear (); + + mainwin_minus_num->hide (); + mainwin_10min_num->hide (); + mainwin_min_num->hide (); + mainwin_10sec_num->hide (); + mainwin_sec_num->hide (); + mainwin_stime_min->hide (); + mainwin_stime_sec->hide (); + mainwin_position->hide (); + mainwin_sposition->hide (); + + mainwin_position->set_pressed (false); + mainwin_sposition->set_pressed (false); + + /* clear sampling parameter displays */ + mainwin_rate_text->set_text (nullptr); + mainwin_freq_text->set_text (nullptr); + mainwin_monostereo->set_num_channels (0); + mainwin_set_othertext (""); + + mainwin_playstatus->set_status (STATUS_STOP); + + playlistwin_hide_timer(); +} + +static void repeat_toggled () +{ + mainwin_repeat->set_active (aud_get_bool (nullptr, "repeat")); +} + +static void shuffle_toggled () +{ + mainwin_shuffle->set_active (aud_get_bool (nullptr, "shuffle")); +} + +static void no_advance_toggled () +{ + if (aud_get_bool (nullptr, "no_playlist_advance")) + mainwin_show_status_message (_("Single mode.")); + else + mainwin_show_status_message (_("Playlist mode.")); +} + +static void stop_after_song_toggled () +{ + if (aud_get_bool (nullptr, "stop_after_current_song")) + mainwin_show_status_message (_("Stopping after song.")); +} + +bool MainWindow::scroll (QWheelEvent * event) +{ + int delta = event->angleDelta ().y () / 24; + if (delta) + mainwin_set_volume_diff (delta); + +#if 0 + case GDK_SCROLL_LEFT: + aud_drct_seek (aud_drct_get_time () - 5000); + break; + case GDK_SCROLL_RIGHT: + aud_drct_seek (aud_drct_get_time () + 5000); + break; +#endif + + return true; +} + +bool MainWindow::button_press (QMouseEvent * event) +{ + if (event->button () == Qt::LeftButton && + event->type () == QEvent::MouseButtonDblClick && + event->y () < 14 * config.scale) + { + mainwin_shade_toggle (); + return true; + } + + if (event->button () == Qt::RightButton && event->type () == QEvent::MouseButtonPress) + { + menu_popup (UI_MENU_MAIN, event->globalX (), event->globalY (), false, false); + return true; + } + + return Window::button_press (event); +} + +static void mainwin_playback_rpress (Button * button, QMouseEvent * event) +{ + menu_popup (UI_MENU_PLAYBACK, event->globalX (), event->globalY (), false, false); +} + +bool Window::keypress (QKeyEvent * event) +{ + if (playlistwin_list->handle_keypress (event)) + return true; + + switch (event->key ()) + { + case Qt::Key_Left: + aud_drct_seek (aud_drct_get_time () - 5000); + break; + case Qt::Key_Right: + aud_drct_seek (aud_drct_get_time () + 5000); + break; + case Qt::Key_Space: + aud_drct_pause (); + break; + default: + return false; + } + + return true; +} + +#if 0 +void mainwin_drag_data_received (GtkWidget * widget, GdkDragContext * context, + int x, int y, GtkSelectionData * selection_data, unsigned info, unsigned time, void *) +{ + g_return_if_fail (selection_data != nullptr); + + const char * data = (const char *) gtk_selection_data_get_data (selection_data); + g_return_if_fail (data); + + if (str_has_prefix_nocase (data, "file:///")) + { + if (str_has_suffix_nocase (data, ".wsz\r\n") || str_has_suffix_nocase + (data, ".zip\r\n")) + { + on_skin_view_drag_data_received (0, context, x, y, selection_data, info, time, 0); + return; + } + } + + audgui_urilist_open (data); +} +#endif + +static int time_now () +{ + struct timeval tv; + gettimeofday (& tv, nullptr); + return (tv.tv_sec % (24 * 3600) * 1000 + tv.tv_usec / 1000); +} + +static int time_diff (int a, int b) +{ + if (a > 18 * 3600 * 1000 && b < 6 * 3600 * 1000) /* detect midnight */ + b += 24 * 3600 * 1000; + return (b > a) ? b - a : 0; +} + +static void seek_timeout (void * rewind) +{ + int held = time_diff (seek_time, time_now ()); + if (held < SEEK_THRESHOLD) + return; + + int position; + if (aud::from_ptr<bool> (rewind)) + position = seek_start - held / SEEK_SPEED; + else + position = seek_start + held / SEEK_SPEED; + + position = aud::clamp (position, 0, 219); + mainwin_position->set_pos (position); + mainwin_position_motion_cb (); +} + +static void seek_press (QMouseEvent * event, bool rewind) +{ + if (event->button () != Qt::LeftButton || seeking) + return; + + seeking = true; + seek_start = mainwin_position->get_pos (); + seek_time = time_now (); + timer_add (TimerRate::Hz10, seek_timeout, aud::to_ptr (rewind)); +} + +static void seek_release (QMouseEvent * event, bool rewind) +{ + if (event->button () != Qt::LeftButton || ! seeking) + return; + + if (! aud_drct_get_playing () || time_diff (seek_time, time_now ()) < + SEEK_THRESHOLD) + { + if (rewind) + aud_drct_pl_prev (); + else + aud_drct_pl_next (); + } + else + mainwin_position_release_cb (); + + seeking = false; + timer_remove (TimerRate::Hz10, seek_timeout); +} + +static void mainwin_rew_press (Button * button, QMouseEvent * event) + { seek_press (event, true); } +static void mainwin_rew_release (Button * button, QMouseEvent * event) + { seek_release (event, true); } +static void mainwin_fwd_press (Button * button, QMouseEvent * event) + { seek_press (event, false); } +static void mainwin_fwd_release (Button * button, QMouseEvent * event) + { seek_release (event, false); } + +static void mainwin_shuffle_cb (Button * button, QMouseEvent * event) + { aud_set_bool (nullptr, "shuffle", button->get_active ()); } +static void mainwin_repeat_cb (Button * button, QMouseEvent * event) + { aud_set_bool (nullptr, "repeat", button->get_active ()); } +static void mainwin_eq_cb (Button * button, QMouseEvent * event) + { view_set_show_equalizer (button->get_active ()); } +static void mainwin_pl_cb (Button * button, QMouseEvent * event) + { view_set_show_playlist (button->get_active ()); } + +static void mainwin_spos_set_knob () +{ + int pos = mainwin_sposition->get_pos (); + int x = (pos < 6) ? 17 : (pos < 9) ? 20 : 23; + mainwin_sposition->set_knob (x, 36, x, 36); +} + +static void mainwin_spos_motion_cb () +{ + mainwin_spos_set_knob (); + + int pos = mainwin_sposition->get_pos (); + int length = aud_drct_get_length (); + int time = (pos - 1) * length / 12; + + char buf[7]; + format_time (buf, time, length); + + mainwin_stime_min->set_text (buf); + mainwin_stime_sec->set_text (buf + 4); +} + +static void mainwin_spos_release_cb () +{ + mainwin_spos_set_knob (); + + int pos = mainwin_sposition->get_pos (); + aud_drct_seek (aud_drct_get_length () * (pos - 1) / 12); +} + +static void mainwin_position_motion_cb () +{ + int length = aud_drct_get_length () / 1000; + int pos = mainwin_position->get_pos (); + int time = pos * length / 219; + + mainwin_lock_info_text (str_printf (_("Seek to %d:%-2.2d / %d:%-2.2d"), + time / 60, time % 60, length / 60, length % 60)); +} + +static void mainwin_position_release_cb () +{ + int length = aud_drct_get_length (); + int pos = mainwin_position->get_pos (); + int time = (int64_t) pos * length / 219; + + aud_drct_seek(time); + mainwin_release_info_text(); +} + +void mainwin_adjust_volume_motion (int v) +{ + aud_drct_set_volume_main (v); + mainwin_lock_info_text (str_printf (_("Volume: %d%%"), v)); +} + +void mainwin_adjust_volume_release () +{ + mainwin_release_info_text (); +} + +void mainwin_adjust_balance_motion (int b) +{ + aud_drct_set_volume_balance (b); + + if (b < 0) + mainwin_lock_info_text (str_printf (_("Balance: %d%% left"), -b)); + else if (b == 0) + mainwin_lock_info_text (_("Balance: center")); + else + mainwin_lock_info_text (str_printf (_("Balance: %d%% right"), b)); +} + +void mainwin_adjust_balance_release () +{ + mainwin_release_info_text (); +} + +static void mainwin_volume_set_frame () +{ + int pos = mainwin_volume->get_pos (); + int frame = (pos * 27 + 25) / 51; + mainwin_volume->set_frame (0, 15 * frame); +} + +void mainwin_set_volume_slider (int percent) +{ + mainwin_volume->set_pos ((percent * 51 + 50) / 100); + mainwin_volume_set_frame (); +} + +static void mainwin_volume_motion_cb () +{ + mainwin_volume_set_frame (); + int pos = mainwin_volume->get_pos (); + int vol = (pos * 100 + 25) / 51; + + mainwin_adjust_volume_motion (vol); + equalizerwin_set_volume_slider (vol); +} + +static void mainwin_volume_release_cb () +{ + mainwin_volume_set_frame (); + mainwin_adjust_volume_release (); +} + +static void mainwin_balance_set_frame () +{ + int pos = mainwin_balance->get_pos (); + int frame = (abs (pos - 12) * 27 + 6) / 12; + mainwin_balance->set_frame (9, 15 * frame); +} + +void mainwin_set_balance_slider (int percent) +{ + if (percent > 0) + mainwin_balance->set_pos (12 + (percent * 12 + 50) / 100); + else + mainwin_balance->set_pos (12 + (percent * 12 - 50) / 100); + + mainwin_balance_set_frame (); +} + +static void mainwin_balance_motion_cb () +{ + mainwin_balance_set_frame (); + int pos = mainwin_balance->get_pos (); + + int bal; + if (pos > 12) + bal = ((pos - 12) * 100 + 6) / 12; + else + bal = ((pos - 12) * 100 - 6) / 12; + + mainwin_adjust_balance_motion (bal); + equalizerwin_set_balance_slider (bal); +} + +static void mainwin_balance_release_cb () +{ + mainwin_balance_set_frame (); + mainwin_adjust_volume_release (); +} + +void mainwin_set_volume_diff (int diff) +{ + int vol = aud_drct_get_volume_main (); + + vol = aud::clamp (vol + diff, 0, 100); + mainwin_adjust_volume_motion (vol); + mainwin_set_volume_slider (vol); + equalizerwin_set_volume_slider (vol); + + mainwin_volume_release_timeout.queue (700, + [] (void *) { mainwin_volume_release_cb (); }, nullptr); +} + +void mainwin_mr_change (MenuRowItem i) +{ + switch (i) + { + case MENUROW_OPTIONS: + mainwin_lock_info_text (_("Options Menu")); + break; + case MENUROW_ALWAYS: + if (aud_get_bool ("skins", "always_on_top")) + mainwin_lock_info_text (_("Disable 'Always On Top'")); + else + mainwin_lock_info_text (_("Enable 'Always On Top'")); + break; + case MENUROW_FILEINFOBOX: + mainwin_lock_info_text (_("File Info Box")); + break; + case MENUROW_SCALE: + mainwin_lock_info_text (_("Double Size")); + break; + case MENUROW_VISUALIZATION: + mainwin_lock_info_text (_("Visualizations")); + break; + default: + break; + } +} + +void mainwin_mr_release (MenuRowItem i, QMouseEvent * event) +{ + switch (i) + { + case MENUROW_OPTIONS: + menu_popup (UI_MENU_VIEW, event->globalX (), event->globalY (), false, false); + break; + case MENUROW_ALWAYS: + view_set_on_top (! aud_get_bool ("skins", "always_on_top")); + break; + case MENUROW_FILEINFOBOX: + audqt::infowin_show_current (); + break; + case MENUROW_SCALE: + view_set_double_size (! aud_get_bool ("skins", "double_size")); + break; + case MENUROW_VISUALIZATION: + audqt::prefswin_show_plugin_page (PluginType::Vis); + break; + default: + break; + } + + mainwin_release_info_text(); +} + +bool change_timer_mode_cb (QMouseEvent * event) +{ + if (event->type () != QEvent::MouseButtonPress || event->button () != Qt::LeftButton) + return false; + + view_set_show_remaining (! aud_get_bool ("skins", "show_remaining_time")); + return true; +} + +static bool mainwin_info_button_press (QMouseEvent * event) +{ + if (event->type () == QEvent::MouseButtonPress && event->button () == Qt::RightButton) + { + menu_popup (UI_MENU_PLAYBACK, event->globalX (), event->globalY (), false, false); + return true; + } + + if (event->type () == QEvent::MouseButtonDblClick && event->button () == Qt::LeftButton) + { + audqt::infowin_show_current (); + return true; + } + + return false; +} + +static void mainwin_create_widgets () +{ + mainwin_menubtn = new Button (9, 9, 0, 0, 0, 9, SKIN_TITLEBAR, SKIN_TITLEBAR); + mainwin->put_widget (false, mainwin_menubtn, 6, 3); + mainwin_menubtn->on_release ((ButtonCB) mainwin_menubtn_cb); + + mainwin_minimize = new Button (9, 9, 9, 0, 9, 9, SKIN_TITLEBAR, SKIN_TITLEBAR); + mainwin->put_widget (false, mainwin_minimize, 244, 3); + mainwin_minimize->on_release ((ButtonCB) mainwin_minimize_cb); + + mainwin_shade = new Button (9, 9, 0, 18, 9, 18, SKIN_TITLEBAR, SKIN_TITLEBAR); + mainwin->put_widget (false, mainwin_shade, 254, 3); + mainwin_shade->on_release ((ButtonCB) mainwin_shade_toggle); + + mainwin_close = new Button (9, 9, 18, 0, 18, 9, SKIN_TITLEBAR, SKIN_TITLEBAR); + mainwin->put_widget (false, mainwin_close, 264, 3); + mainwin_close->on_release ((ButtonCB) skins_close); + + mainwin_rew = new Button (23, 18, 0, 0, 0, 18, SKIN_CBUTTONS, SKIN_CBUTTONS); + mainwin->put_widget (false, mainwin_rew, 16, 88); + mainwin_rew->on_press (mainwin_rew_press); + mainwin_rew->on_release (mainwin_rew_release); + mainwin_rew->on_rpress (mainwin_playback_rpress); + + mainwin_fwd = new Button (22, 18, 92, 0, 92, 18, SKIN_CBUTTONS, SKIN_CBUTTONS); + mainwin->put_widget (false, mainwin_fwd, 108, 88); + mainwin_fwd->on_press (mainwin_fwd_press); + mainwin_fwd->on_release (mainwin_fwd_release); + mainwin_fwd->on_rpress (mainwin_playback_rpress); + + mainwin_play = new Button (23, 18, 23, 0, 23, 18, SKIN_CBUTTONS, SKIN_CBUTTONS); + mainwin->put_widget (false, mainwin_play, 39, 88); + mainwin_play->on_release ((ButtonCB) aud_drct_play); + mainwin_play->on_rpress (mainwin_playback_rpress); + + mainwin_pause = new Button (23, 18, 46, 0, 46, 18, SKIN_CBUTTONS, SKIN_CBUTTONS); + mainwin->put_widget (false, mainwin_pause, 62, 88); + mainwin_pause->on_release ((ButtonCB) aud_drct_pause); + mainwin_pause->on_rpress (mainwin_playback_rpress); + + mainwin_stop = new Button (23, 18, 69, 0, 69, 18, SKIN_CBUTTONS, SKIN_CBUTTONS); + mainwin->put_widget (false, mainwin_stop, 85, 88); + mainwin_stop->on_release ((ButtonCB) aud_drct_stop); + mainwin_stop->on_rpress (mainwin_playback_rpress); + + mainwin_eject = new Button (22, 16, 114, 0, 114, 16, SKIN_CBUTTONS, SKIN_CBUTTONS); + mainwin->put_widget (false, mainwin_eject, 136, 89); + mainwin_eject->on_release ((ButtonCB) action_play_file); + + mainwin_shuffle = new Button (46, 15, 28, 0, 28, 15, 28, 30, 28, 45, SKIN_SHUFREP, SKIN_SHUFREP); + mainwin->put_widget (false, mainwin_shuffle, 164, 89); + mainwin_shuffle->set_active (aud_get_bool (nullptr, "shuffle")); + mainwin_shuffle->on_release (mainwin_shuffle_cb); + + mainwin_repeat = new Button (28, 15, 0, 0, 0, 15, 0, 30, 0, 45, SKIN_SHUFREP, SKIN_SHUFREP); + mainwin->put_widget (false, mainwin_repeat, 210, 89); + mainwin_repeat->set_active (aud_get_bool (nullptr, "repeat")); + mainwin_repeat->on_release (mainwin_repeat_cb); + + mainwin_eq = new Button (23, 12, 0, 61, 46, 61, 0, 73, 46, 73, SKIN_SHUFREP, SKIN_SHUFREP); + mainwin->put_widget (false, mainwin_eq, 219, 58); + mainwin_eq->on_release (mainwin_eq_cb); + + mainwin_pl = new Button (23, 12, 23, 61, 69, 61, 23, 73, 69, 73, SKIN_SHUFREP, SKIN_SHUFREP); + mainwin->put_widget (false, mainwin_pl, 242, 58); + mainwin_pl->on_release (mainwin_pl_cb); + + String font; + if (! config.mainwin_use_bitmapfont) + font = aud_get_str ("skins", "mainwin_font"); + + bool shaded = aud_get_bool ("skins", "mainwin_shaded"); + mainwin_info = new TextBox (153, font, ! shaded && config.autoscroll); + mainwin->put_widget (false, mainwin_info, 112, 27); + mainwin_info->on_press (mainwin_info_button_press); + + mainwin_othertext = new TextBox (153, nullptr, false); + mainwin->put_widget (false, mainwin_othertext, 112, 43); + + mainwin_rate_text = new TextBox (15, nullptr, false); + mainwin->put_widget (false, mainwin_rate_text, 111, 43); + + mainwin_freq_text = new TextBox (10, nullptr, false); + mainwin->put_widget (false, mainwin_freq_text, 156, 43); + + mainwin_menurow = new MenuRow; + mainwin->put_widget (false, mainwin_menurow, 10, 22); + + mainwin_volume = new HSlider (0, 51, SKIN_VOLUME, 68, 13, 0, 0, 14, 11, 15, 422, 0, 422); + mainwin->put_widget (false, mainwin_volume, 107, 57); + mainwin_volume->on_move (mainwin_volume_motion_cb); + mainwin_volume->on_release (mainwin_volume_release_cb); + + mainwin_balance = new HSlider (0, 24, SKIN_BALANCE, 38, 13, 9, 0, 14, 11, 15, 422, 0, 422); + mainwin->put_widget (false, mainwin_balance, 177, 57); + mainwin_balance->on_move (mainwin_balance_motion_cb); + mainwin_balance->on_release (mainwin_balance_release_cb); + + mainwin_monostereo = new MonoStereo; + mainwin->put_widget (false, mainwin_monostereo, 212, 41); + + mainwin_playstatus = new PlayStatus; + mainwin->put_widget (false, mainwin_playstatus, 24, 28); + + mainwin_minus_num = new SkinnedNumber; + mainwin->put_widget (false, mainwin_minus_num, 36, 26); + + mainwin_10min_num = new SkinnedNumber; + mainwin->put_widget (false, mainwin_10min_num, 48, 26); + + mainwin_min_num = new SkinnedNumber; + mainwin->put_widget (false, mainwin_min_num, 60, 26); + + mainwin_10sec_num = new SkinnedNumber; + mainwin->put_widget (false, mainwin_10sec_num, 78, 26); + + mainwin_sec_num = new SkinnedNumber; + mainwin->put_widget (false, mainwin_sec_num, 90, 26); + + mainwin_about = new Button (20, 25); + mainwin->put_widget (false, mainwin_about, 247, 83); + mainwin_about->on_release ((ButtonCB) audqt::aboutwindow_show); + + mainwin_vis = new SkinnedVis; + mainwin->put_widget (false, mainwin_vis, 24, 43); + + mainwin_position = new HSlider (0, 219, SKIN_POSBAR, 248, 10, 0, 0, 29, 10, 248, 0, 278, 0); + mainwin->put_widget (false, mainwin_position, 16, 72); + mainwin_position->on_move (mainwin_position_motion_cb); + mainwin_position->on_release (mainwin_position_release_cb); + + /* shaded */ + + mainwin_shaded_menubtn = new Button (9, 9, 0, 0, 0, 9, SKIN_TITLEBAR, SKIN_TITLEBAR); + mainwin->put_widget (true, mainwin_shaded_menubtn, 6, 3); + mainwin_shaded_menubtn->on_release ((ButtonCB) mainwin_menubtn_cb); + + mainwin_shaded_minimize = new Button (9, 9, 9, 0, 9, 9, SKIN_TITLEBAR, SKIN_TITLEBAR); + mainwin->put_widget (true, mainwin_shaded_minimize, 244, 3); + mainwin_shaded_minimize->on_release ((ButtonCB) mainwin_minimize_cb); + + mainwin_shaded_shade = new Button (9, 9, 0, 27, 9, 27, SKIN_TITLEBAR, SKIN_TITLEBAR); + mainwin->put_widget (true, mainwin_shaded_shade, 254, 3); + mainwin_shaded_shade->on_release ((ButtonCB) mainwin_shade_toggle); + + mainwin_shaded_close = new Button (9, 9, 18, 0, 18, 9, SKIN_TITLEBAR, SKIN_TITLEBAR); + mainwin->put_widget (true, mainwin_shaded_close, 264, 3); + mainwin_shaded_close->on_release ((ButtonCB) skins_close); + + mainwin_srew = new Button (8, 7); + mainwin->put_widget (true, mainwin_srew, 169, 4); + mainwin_srew->on_release ((ButtonCB) aud_drct_pl_prev); + + mainwin_splay = new Button (10, 7); + mainwin->put_widget (true, mainwin_splay, 177, 4); + mainwin_splay->on_release ((ButtonCB) aud_drct_play); + + mainwin_spause = new Button (10, 7); + mainwin->put_widget (true, mainwin_spause, 187, 4); + mainwin_spause->on_release ((ButtonCB) aud_drct_pause); + + mainwin_sstop = new Button (9, 7); + mainwin->put_widget (true, mainwin_sstop, 197, 4); + mainwin_sstop->on_release ((ButtonCB) aud_drct_stop); + + mainwin_sfwd = new Button (8, 7); + mainwin->put_widget (true, mainwin_sfwd, 206, 4); + mainwin_sfwd->on_release ((ButtonCB) aud_drct_pl_next); + + mainwin_seject = new Button (9, 7); + mainwin->put_widget (true, mainwin_seject, 216, 4); + mainwin_seject->on_release ((ButtonCB) action_play_file); + + mainwin_svis = new SmallVis (); + mainwin->put_widget (true, mainwin_svis, 79, 5); + + mainwin_sposition = new HSlider (1, 13, SKIN_TITLEBAR, 17, 7, 0, 36, 3, 7, 17, 36, 17, 36); + mainwin->put_widget (true, mainwin_sposition, 226, 4); + mainwin_sposition->on_move (mainwin_spos_motion_cb); + mainwin_sposition->on_release (mainwin_spos_release_cb); + + mainwin_stime_min = new TextBox (15, nullptr, false); + mainwin->put_widget (true, mainwin_stime_min, 130, 4); + mainwin_stime_min->on_press (change_timer_mode_cb); + + mainwin_stime_sec = new TextBox (10, nullptr, false); + mainwin->put_widget (true, mainwin_stime_sec, 147, 4); + mainwin_stime_sec->on_press (change_timer_mode_cb); +} + +#if 0 +static gboolean state_cb (GtkWidget * widget, GdkEventWindowState * event, void *) +{ + if (event->changed_mask & GDK_WINDOW_STATE_STICKY) + view_set_sticky (!! (event->new_window_state & GDK_WINDOW_STATE_STICKY)); + + if (event->changed_mask & GDK_WINDOW_STATE_ABOVE) + view_set_on_top (!! (event->new_window_state & GDK_WINDOW_STATE_ABOVE)); + + return true; +} +#endif + +void MainWindow::draw (QPainter & cr) +{ + int width = is_shaded () ? MAINWIN_SHADED_WIDTH : skin.hints.mainwin_width; + int height = is_shaded () ? MAINWIN_SHADED_HEIGHT : skin.hints.mainwin_height; + + skin_draw_pixbuf (cr, SKIN_MAIN, 0, 0, 0, 0, width, height); + skin_draw_mainwin_titlebar (cr, is_shaded (), true); +} + +static void mainwin_create_window () +{ + bool shaded = aud_get_bool ("skins", "player_shaded"); + + mainwin = new MainWindow (shaded); + mainwin->setWindowTitle (_("Audacious")); + +#if 0 + GtkWidget * w = mainwin->gtk (); + drag_dest_set (w); + + g_signal_connect (w, "drag-data-received", (GCallback) mainwin_drag_data_received, nullptr); + g_signal_connect (w, "window-state-event", (GCallback) state_cb, nullptr); +#endif + + hook_associate ("playback begin", (HookFunction) mainwin_playback_begin, nullptr); + hook_associate ("playback ready", (HookFunction) mainwin_playback_begin, nullptr); + hook_associate ("playback seek", (HookFunction) mainwin_update_song_info, nullptr); + hook_associate ("playback stop", (HookFunction) mainwin_playback_stop, nullptr); + hook_associate ("playback pause", (HookFunction) playback_pause, nullptr); + hook_associate ("playback unpause", (HookFunction) playback_unpause, nullptr); + hook_associate ("title change", (HookFunction) title_change, nullptr); + hook_associate ("info change", (HookFunction) info_change, nullptr); + hook_associate ("set repeat", (HookFunction) repeat_toggled, nullptr); + hook_associate ("set shuffle", (HookFunction) shuffle_toggled, nullptr); + hook_associate ("set no_playlist_advance", (HookFunction) no_advance_toggled, nullptr); + hook_associate ("set stop_after_current_song", (HookFunction) stop_after_song_toggled, nullptr); +} + +void mainwin_unhook () +{ + seeking = false; + timer_remove (TimerRate::Hz10, seek_timeout); + + status_message_timeout.stop (); + mainwin_volume_release_timeout.stop (); + + hook_dissociate ("playback begin", (HookFunction) mainwin_playback_begin); + hook_dissociate ("playback ready", (HookFunction) mainwin_playback_begin); + hook_dissociate ("playback seek", (HookFunction) mainwin_update_song_info); + hook_dissociate ("playback stop", (HookFunction) mainwin_playback_stop); + hook_dissociate ("playback pause", (HookFunction) playback_pause); + hook_dissociate ("playback unpause", (HookFunction) playback_unpause); + hook_dissociate ("title change", (HookFunction) title_change); + hook_dissociate ("info change", (HookFunction) info_change); + hook_dissociate ("set repeat", (HookFunction) repeat_toggled); + hook_dissociate ("set shuffle", (HookFunction) shuffle_toggled); + hook_dissociate ("set no_playlist_advance", (HookFunction) no_advance_toggled); + hook_dissociate ("set stop_after_current_song", (HookFunction) stop_after_song_toggled); + + start_stop_visual (true); + + locked_textbox = nullptr; + locked_old_text = String (); +} + +void mainwin_create () +{ + mainwin_create_window (); + mainwin_create_widgets (); +} + +static void mainwin_update_volume () +{ + int volume = aud_drct_get_volume_main (); + int balance = aud_drct_get_volume_balance (); + + mainwin_set_volume_slider (volume); + mainwin_set_balance_slider (balance); + equalizerwin_set_volume_slider (volume); + equalizerwin_set_balance_slider (balance); +} + +static void mainwin_update_time_display (int time, int length) +{ + char scratch[7]; + format_time (scratch, time, length); + + mainwin_minus_num->set (scratch[0]); + mainwin_10min_num->set (scratch[1]); + mainwin_min_num->set (scratch[2]); + mainwin_10sec_num->set (scratch[4]); + mainwin_sec_num->set (scratch[5]); + + if (! mainwin_sposition->get_pressed ()) + { + mainwin_stime_min->set_text (scratch); + mainwin_stime_sec->set_text (scratch + 4); + } + + playlistwin_set_time (scratch, scratch + 4); +} + +static void mainwin_update_time_slider (int time, int length) +{ + mainwin_position->setVisible (length > 0); + mainwin_sposition->setVisible (length > 0); + + if (length > 0 && ! seeking) + { + if (time < length) + { + mainwin_position->set_pos (time * (int64_t) 219 / length); + mainwin_sposition->set_pos (1 + time * (int64_t) 12 / length); + } + else + { + mainwin_position->set_pos (219); + mainwin_sposition->set_pos (13); + } + + mainwin_spos_set_knob (); + } +} + +void mainwin_update_song_info () +{ + mainwin_update_volume (); + + if (! aud_drct_get_playing ()) + return; + + int time = 0, length = 0; + if (aud_drct_get_ready ()) + { + time = aud_drct_get_time (); + length = aud_drct_get_length (); + } + + mainwin_update_time_display (time, length); + mainwin_update_time_slider (time, length); +} diff --git a/src/skins/ui_main.h b/src/skins-qt/main.h index e194eee..5adbe32 100644 --- a/src/skins/ui_main.h +++ b/src/skins-qt/main.h @@ -23,54 +23,47 @@ #ifndef SKINS_UI_MAIN_H #define SKINS_UI_MAIN_H -#include <gtk/gtk.h> - /* yes, main window size is fixed */ #define MAINWIN_WIDTH (int)275 #define MAINWIN_HEIGHT (int)116 -#define MAINWIN_TITLEBAR_HEIGHT (int)14 #define MAINWIN_SHADED_WIDTH MAINWIN_WIDTH -#define MAINWIN_SHADED_HEIGHT MAINWIN_TITLEBAR_HEIGHT - -extern GtkWidget *mainwin; - -extern GtkWidget *mainwin_shuffle, *mainwin_repeat; -extern GtkWidget *mainwin_eq, *mainwin_pl; -extern GtkWidget *mainwin_info; +#define MAINWIN_SHADED_HEIGHT (int)14 -extern GtkWidget *mainwin_stime_min, *mainwin_stime_sec; +class Button; +class MenuRow; +class QMouseEvent; +class SkinnedVis; +class SmallVis; +class TextBox; +class Window; -extern GtkWidget *mainwin_vis; -extern GtkWidget *mainwin_svis; +extern Window * mainwin; -extern GtkWidget *mainwin_playstatus; +extern Button * mainwin_eq, * mainwin_pl; +extern TextBox * mainwin_info; +extern MenuRow * mainwin_menurow; -extern GtkWidget *mainwin_minus_num, *mainwin_10min_num, *mainwin_min_num; -extern GtkWidget *mainwin_10sec_num, *mainwin_sec_num; +extern SkinnedVis * mainwin_vis; +extern SmallVis * mainwin_svis; -extern GtkWidget *mainwin_menurow; -extern GtkWidget *mainwin_position, *mainwin_sposition; +void mainwin_create (); +void mainwin_unhook (); -void mainwin_create(void); -void mainwin_unhook (void); +void mainwin_adjust_volume_motion (int v); +void mainwin_adjust_volume_release (); +void mainwin_adjust_balance_motion (int b); +void mainwin_adjust_balance_release (); +void mainwin_set_volume_slider (int percent); +void mainwin_set_balance_slider (int percent); +void mainwin_set_volume_diff (int diff); -void mainwin_adjust_volume_motion(int v); -void mainwin_adjust_volume_release(void); -void mainwin_adjust_balance_motion(int b); -void mainwin_adjust_balance_release(void); -void mainwin_set_volume_slider(int percent); -void mainwin_set_balance_slider(int percent); +void mainwin_refresh_hints (); +void mainwin_playback_begin (); -void mainwin_refresh_hints(void); -void mainwin_set_song_title (const char * title); -void mainwin_set_song_info(int rate, int freq, int nch); -void mainwin_clear_song_info(void); - -void mainwin_disable_seekbar(void); - -void mainwin_update_song_info (void); +void mainwin_update_song_info (); void mainwin_show_status_message (const char * message); +#if 0 void mainwin_drag_data_received(GtkWidget * widget, GdkDragContext * context, int x, @@ -79,11 +72,8 @@ void mainwin_drag_data_received(GtkWidget * widget, unsigned info, unsigned time, void * user_data); +#endif -gboolean change_timer_mode_cb(GtkWidget *widget, GdkEventButton *event); - -/* widget should be null if called manually. */ -gboolean mainwin_keypress (GtkWidget * widget, GdkEventKey * event, - void * unused); +bool change_timer_mode_cb (QMouseEvent * event); #endif /* SKINS_UI_MAIN_H */ diff --git a/src/skins-qt/menurow.cc b/src/skins-qt/menurow.cc new file mode 100644 index 0000000..cab3391 --- /dev/null +++ b/src/skins-qt/menurow.cc @@ -0,0 +1,122 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2011 John Lindgren + * + * Based on: + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include <libaudcore/runtime.h> + +#include "skins_cfg.h" +#include "skin.h" +#include "menurow.h" + +void MenuRow::draw (QPainter & cr) +{ + if (m_selected == MENUROW_NONE) + { + if (m_pushed) + skin_draw_pixbuf (cr, SKIN_TITLEBAR, 304, 0, 0, 0, 8, 43); + else + skin_draw_pixbuf (cr, SKIN_TITLEBAR, 312, 0, 0, 0, 8, 43); + } + else + skin_draw_pixbuf (cr, SKIN_TITLEBAR, 304 + 8 * (m_selected - 1), 44, 0, 0, 8, 43); + + if (m_pushed) + { + if (aud_get_bool ("skins", "always_on_top")) + skin_draw_pixbuf (cr, SKIN_TITLEBAR, 312, 54, 0, 10, 8, 8); + if (aud_get_bool ("skins", "double_size")) + skin_draw_pixbuf (cr, SKIN_TITLEBAR, 328, 70, 0, 26, 8, 8); + } +} + +static MenuRowItem menurow_find_selected (int x, int y) +{ + if (x >= 0 && x < 8) + { + if (y >= 0 && y < 10) + return MENUROW_OPTIONS; + if (y >= 10 && y < 18) + return MENUROW_ALWAYS; + if (y >= 18 && y < 26) + return MENUROW_FILEINFOBOX; + if (y >= 26 && y < 34) + return MENUROW_SCALE; + if (y >= 34 && y < 43) + return MENUROW_VISUALIZATION; + } + + return MENUROW_NONE; +} + +bool MenuRow::button_press (QMouseEvent * event) +{ + if (event->button () != Qt::LeftButton) + return false; + + m_pushed = true; + m_selected = menurow_find_selected (event->x () / config.scale, event->y () / config.scale); + + mainwin_mr_change (m_selected); + + queue_draw (); + return true; +} + +bool MenuRow::button_release (QMouseEvent * event) +{ + if (event->button () != Qt::LeftButton) + return false; + + if (! m_pushed) + return true; + + mainwin_mr_release (m_selected, event); + + m_pushed = false; + m_selected = MENUROW_NONE; + + queue_draw (); + return true; +} + +bool MenuRow::motion (QMouseEvent * event) +{ + if (! m_pushed) + return true; + + m_selected = menurow_find_selected (event->x () / config.scale, event->y () / config.scale); + + mainwin_mr_change (m_selected); + + queue_draw (); + return true; +} + +MenuRow::MenuRow () +{ + set_scale (config.scale); + add_input (8, 43, true, true); +} diff --git a/src/skins-qt/menurow.h b/src/skins-qt/menurow.h new file mode 100644 index 0000000..b0862d4 --- /dev/null +++ b/src/skins-qt/menurow.h @@ -0,0 +1,62 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2011 John Lindgren + * + * Based on: + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#ifndef SKINS_UI_SKINNED_MENUROW_H +#define SKINS_UI_SKINNED_MENUROW_H + +#include "widget.h" + +enum MenuRowItem { + MENUROW_NONE, + MENUROW_OPTIONS, + MENUROW_ALWAYS, + MENUROW_FILEINFOBOX, + MENUROW_SCALE, + MENUROW_VISUALIZATION +}; + +class MenuRow : public Widget +{ +public: + MenuRow (); + void refresh () { queue_draw (); } + +private: + virtual void draw (QPainter & cr); + virtual bool button_press (QMouseEvent * event); + virtual bool button_release (QMouseEvent * event); + virtual bool motion (QMouseEvent * event); + + MenuRowItem m_selected = MENUROW_NONE; + bool m_pushed = false; +}; + +/* callbacks in ui_main.c */ +void mainwin_mr_change (MenuRowItem i); +void mainwin_mr_release (MenuRowItem i, QMouseEvent * event); + +#endif diff --git a/src/skins-qt/menus.cc b/src/skins-qt/menus.cc new file mode 100644 index 0000000..f42019b --- /dev/null +++ b/src/skins-qt/menus.cc @@ -0,0 +1,295 @@ +/* + * menus.c + * Copyright 2010-2014 John Lindgren + * + * This file is part of Audacious. + * + * Audacious 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, version 2 or version 3 of the License. + * + * Audacious 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 + * Audacious. If not, see <http://www.gnu.org/licenses/>. + * + * The Audacious team does not consider modular code linking to Audacious or + * using our public API to be a derived work. + */ + +#include "menus.h" + +#include <QMenu> + +#include <libaudcore/drct.h> +#include <libaudcore/hook.h> +#include <libaudcore/i18n.h> +#include <libaudcore/interface.h> +#include <libaudcore/plugins.h> +#include <libaudcore/runtime.h> +#include <libaudqt/menu.h> + +#include "actions-mainwin.h" +#include "actions-playlist.h" +#include "main.h" +#include "view.h" + +static QMenu * menus[UI_MENUS]; + +/* note: playback, playlist, and view menus must be created before main menu */ +static QMenu * get_menu_playback () { return menus[UI_MENU_PLAYBACK]; } +static QMenu * get_menu_playlist () { return menus[UI_MENU_PLAYLIST]; } +static QMenu * get_menu_view () { return menus[UI_MENU_VIEW]; } + +static QMenu * get_plugin_menu_main () { return audqt::menu_get_by_id (AudMenuID::Main); } +static QMenu * get_plugin_menu_playlist () { return audqt::menu_get_by_id (AudMenuID::Playlist); } +static QMenu * get_plugin_menu_playlist_add () { return audqt::menu_get_by_id (AudMenuID::PlaylistAdd); } +static QMenu * get_plugin_menu_playlist_remove () { return audqt::menu_get_by_id (AudMenuID::PlaylistRemove); } + +static void configure_effects () { audqt::prefswin_show_plugin_page (PluginType::Effect); } +static void configure_output () { audqt::prefswin_show_plugin_page (PluginType::Output); } +static void configure_visualizations () { audqt::prefswin_show_plugin_page (PluginType::Vis); } + +static void volume_up () { mainwin_set_volume_diff (5); } +static void volume_down () { mainwin_set_volume_diff (-5); } + +/* emulate a config item for the recording toggle */ +static void toggle_record () +{ + bool enable = aud_get_bool ("skins", "record"); + + if (aud_drct_enable_record (enable)) + mainwin_show_status_message (enable ? _("Recording on") : _("Recording off")); + else + { + aud_set_bool ("skins", "record", aud_drct_get_record_enabled ()); + hook_call ("skins set record", nullptr); + } +} + +static void record_toggled (void * = nullptr, void * = nullptr) +{ + bool enabled = aud_drct_get_record_enabled (); + if (enabled != aud_get_bool ("skins", "record")) + { + aud_set_bool ("skins", "record", enabled); + hook_call ("skins set record", nullptr); + } +} + +static const audqt::MenuItem output_items[] = { + audqt::MenuCommand ({N_("Volume Up"), "audio-volume-high", "+"}, volume_up), + audqt::MenuCommand ({N_("Volume Down"), "audio-volume-low", "-"}, volume_down), + audqt::MenuSep (), + audqt::MenuCommand ({N_("Effects ...")}, configure_effects), + audqt::MenuSep (), + audqt::MenuToggle ({N_("Record Stream"), "media-record", "D"}, {"skins", "record", "skins set record"}, toggle_record), + audqt::MenuCommand ({N_("Audio Settings ..."), "audio-card"}, configure_output) +}; + +static const audqt::MenuItem main_items[] = { + audqt::MenuCommand ({N_("Open Files ..."), "document-open", "L"}, action_play_file), + audqt::MenuCommand ({N_("Open Folder ..."), "document-open", "Shift+L"}, action_play_folder), + audqt::MenuCommand ({N_("Open URL ..."), "folder-remote", "Ctrl+L"}, action_play_location), +// audqt::MenuCommand ({N_("Search Library"), "edit-find", "Y"}, action_search_tool), + audqt::MenuSep (), + audqt::MenuSub ({N_("Playback")}, get_menu_playback), + audqt::MenuSub ({N_("Playlist")}, get_menu_playlist), + audqt::MenuSub ({N_("Output")}, {output_items}), + audqt::MenuSub ({N_("View")}, get_menu_view), + audqt::MenuSep (), + audqt::MenuSub ({N_("Services")}, get_plugin_menu_main), + audqt::MenuSep (), + audqt::MenuCommand ({N_("About ..."), "help-about"}, audqt::aboutwindow_show), + audqt::MenuCommand ({N_("Settings ..."), "preferences-system", "Ctrl+P"}, audqt::prefswin_show), + audqt::MenuCommand ({N_("Quit"), "application-exit", "Ctrl+Q"}, aud_quit) +}; + +static const audqt::MenuItem playback_items[] = { + audqt::MenuCommand ({N_("Song Info ..."), "dialog-information", "I"}, audqt::infowin_show_current), + audqt::MenuSep (), + audqt::MenuToggle ({N_("Repeat"), "media-playlist-repeat", "R"}, {nullptr, "repeat", "set repeat"}), + audqt::MenuToggle ({N_("Shuffle"), "media-playlist-shuffle", "S"}, {nullptr, "shuffle", "set shuffle"}), + audqt::MenuToggle ({N_("Shuffle by Album")}, {nullptr, "album_shuffle", "set album_shuffle"}), + audqt::MenuToggle ({N_("No Playlist Advance"), nullptr, "Ctrl+N"}, {nullptr, "no_playlist_advance", "set no_playlist_advance"}), + audqt::MenuToggle ({N_("Stop After This Song"), nullptr, "Ctrl+M"}, {nullptr, "stop_after_current_song", "set stop_after_current_song"}), + audqt::MenuSep (), + audqt::MenuCommand ({N_("Play"), "media-playback-start", "X"}, aud_drct_play), + audqt::MenuCommand ({N_("Pause"), "media-playback-pause", "C"}, aud_drct_pause), + audqt::MenuCommand ({N_("Stop"), "media-playback-stop", "V"}, aud_drct_stop), + audqt::MenuCommand ({N_("Previous"), "media-skip-backward", "Z"}, aud_drct_pl_prev), + audqt::MenuCommand ({N_("Next"), "media-skip-forward", "B"}, aud_drct_pl_next), + audqt::MenuSep (), + audqt::MenuCommand ({N_("Set A-B Repeat"), nullptr, "A"}, action_ab_set), + audqt::MenuCommand ({N_("Clear A-B Repeat"), nullptr, "Shift+A"}, action_ab_clear), +#if 0 + audqt::MenuSep (), + audqt::MenuCommand ({N_("Jump to Song ..."), "go-jump", "J"}, audgui_jump_to_track), + audqt::MenuCommand ({N_("Jump to Time ..."), "go-jump", "Ctrl+J"}, audgui_jump_to_time) +#endif +}; + +static const audqt::MenuItem playlist_items[] = { + audqt::MenuCommand ({N_("Play/Resume"), "media-playback-start", "Shift+Return"}, action_playlist_play), + audqt::MenuSep (), + audqt::MenuCommand ({N_("New Playlist"), "document-new", "Shift+N"}, action_playlist_new), + audqt::MenuCommand ({N_("Rename Playlist ..."), "insert-text", "F2"}, action_playlist_rename), + audqt::MenuCommand ({N_("Remove Playlist"), "edit-delete", "Shift+D"}, action_playlist_delete), + audqt::MenuSep (), + audqt::MenuCommand ({N_("Previous Playlist"), "media-skip-backward", "Shift+Tab"}, action_playlist_prev), + audqt::MenuCommand ({N_("Next Playlist"), "media-skip-forward", "Tab"}, action_playlist_next), + audqt::MenuSep (), +#if 0 + audqt::MenuCommand ({N_("Import Playlist ..."), "document-open", "O"}, audgui_import_playlist), + audqt::MenuCommand ({N_("Export Playlist ..."), "document-save", "Shift+S"}, audgui_export_playlist), + audqt::MenuSep (), +#endif + audqt::MenuCommand ({N_("Playlist Manager ..."), "audio-x-generic", "P"}, action_playlist_manager), + audqt::MenuCommand ({N_("Queue Manager ..."), nullptr, "Ctrl+U"}, audqt::queue_manager_show), + audqt::MenuSep (), + audqt::MenuCommand ({N_("Refresh Playlist"), "view-refresh", "F5"}, action_playlist_refresh_list) +}; + +static const audqt::MenuItem view_items[] = { + audqt::MenuToggle ({N_("Show Playlist Editor"), nullptr, "Alt+E"}, {"skins", "playlist_visible", "skins set playlist_visible"}, view_apply_show_playlist), + audqt::MenuToggle ({N_("Show Equalizer"), nullptr, "Alt+G"}, {"skins", "equalizer_visible", "skins set equalizer_visible"}, view_apply_show_equalizer), + audqt::MenuSep (), + audqt::MenuToggle ({N_("Show Remaining Time"), nullptr, "Ctrl+R"}, {"skins", "show_remaining_time", "skins set show_remaining_time"}, view_apply_show_remaining), + audqt::MenuSep (), + audqt::MenuToggle ({N_("Double Size"), nullptr, "Ctrl+D"}, {"skins", "double_size", "skins set double_size"}, view_apply_double_size), +#if 0 + audqt::MenuToggle ({N_("Always on Top"), nullptr, "Ctrl+O"}, {"skins", "always_on_top", "skins set always_on_top"}, view_apply_on_top), + audqt::MenuToggle ({N_("On All Workspaces"), nullptr, "Ctrl+S"}, {"skins", "sticky", "skins set sticky"}, view_apply_sticky), +#endif + audqt::MenuSep (), + audqt::MenuToggle ({N_("Roll Up Player"), nullptr, "Ctrl+W"}, {"skins", "player_shaded", "skins set player_shaded"}, view_apply_player_shaded), + audqt::MenuToggle ({N_("Roll Up Playlist Editor"), nullptr, "Shift+Ctrl+W"}, {"skins", "playlist_shaded", "skins set playlist_shaded"}, view_apply_playlist_shaded), + audqt::MenuToggle ({N_("Roll Up Equalizer"), nullptr, "Ctrl+Alt+W"}, {"skins", "equalizer_shaded", "skins set equalizer_shaded"}, view_apply_equalizer_shaded), + audqt::MenuSep (), + audqt::MenuCommand ({N_("_Visualizations ...")}, configure_visualizations) +}; + +static const audqt::MenuItem playlist_add_items[] = { + audqt::MenuSub ({N_("Services")}, get_plugin_menu_playlist_add), + audqt::MenuSep (), + audqt::MenuCommand ({N_("Add URL ..."), "folder-remote", "Ctrl+H"}, action_playlist_add_url), + audqt::MenuCommand ({N_("Add Folder ..."), "list-add", "Shift+F"}, action_playlist_add_folder), + audqt::MenuCommand ({N_("Add Files ..."), "list-add", "F"}, action_playlist_add_files) +}; + +static const audqt::MenuItem dupe_items[] = { + audqt::MenuCommand ({N_("By Title")}, action_playlist_remove_dupes_by_title), + audqt::MenuCommand ({N_("By File Name")}, action_playlist_remove_dupes_by_filename), + audqt::MenuCommand ({N_("By File Path")}, action_playlist_remove_dupes_by_full_path) +}; + +static const audqt::MenuItem playlist_remove_items[] = { + audqt::MenuSub ({N_("Services")}, get_plugin_menu_playlist_remove), + audqt::MenuSep (), + audqt::MenuCommand ({N_("Remove All"), "edit-delete"}, action_playlist_remove_all), + audqt::MenuCommand ({N_("Clear Queue"), "edit-clear", "Shift+Q"}, action_playlist_clear_queue), + audqt::MenuSep (), + audqt::MenuCommand ({N_("Remove Unavailable Files"), "dialog-warning"}, action_playlist_remove_unavailable), + audqt::MenuSub ({N_("Remove Duplicates"), "edit-copy"}, {dupe_items}), + audqt::MenuSep (), + audqt::MenuCommand ({N_("Remove Unselected"), "list-remove"}, action_playlist_remove_unselected), + audqt::MenuCommand ({N_("Remove Selected"), "list-remove", "Delete"}, action_playlist_remove_selected) +}; + +static const audqt::MenuItem playlist_select_items[] = { + audqt::MenuCommand ({N_("Invert Selection")}, action_playlist_invert_selection), + audqt::MenuCommand ({N_("Select None"), nullptr, "Shift+Ctrl+A"}, action_playlist_select_none), + audqt::MenuCommand ({N_("Select All"), "edit-select-all", "Ctrl+A"}, action_playlist_select_all), +}; + +static const audqt::MenuItem sort_items[] = { + audqt::MenuCommand ({N_("By Track Number")}, action_playlist_sort_by_track_number), + audqt::MenuCommand ({N_("By Title")}, action_playlist_sort_by_title), + audqt::MenuCommand ({N_("By Artist")}, action_playlist_sort_by_artist), + audqt::MenuCommand ({N_("By Album")}, action_playlist_sort_by_album), + audqt::MenuCommand ({N_("By Album Artist")}, action_playlist_sort_by_album_artist), + audqt::MenuCommand ({N_("By Release Date")}, action_playlist_sort_by_date), + audqt::MenuCommand ({N_("By Genre")}, action_playlist_sort_by_genre), + audqt::MenuCommand ({N_("By Length")}, action_playlist_sort_by_length), + audqt::MenuCommand ({N_("By File Name")}, action_playlist_sort_by_filename), + audqt::MenuCommand ({N_("By File Path")}, action_playlist_sort_by_full_path), + audqt::MenuCommand ({N_("By Custom Title")}, action_playlist_sort_by_custom_title) +}; + +static const audqt::MenuItem sort_selected_items[] = { + audqt::MenuCommand ({N_("By Track Number")}, action_playlist_sort_selected_by_track_number), + audqt::MenuCommand ({N_("By Title")}, action_playlist_sort_selected_by_title), + audqt::MenuCommand ({N_("By Artist")}, action_playlist_sort_selected_by_artist), + audqt::MenuCommand ({N_("By Album")}, action_playlist_sort_selected_by_album), + audqt::MenuCommand ({N_("By Album Artist")}, action_playlist_sort_selected_by_album_artist), + audqt::MenuCommand ({N_("By Genre")}, action_playlist_sort_selected_by_genre), + audqt::MenuCommand ({N_("By Release Date")}, action_playlist_sort_selected_by_date), + audqt::MenuCommand ({N_("By Length")}, action_playlist_sort_selected_by_length), + audqt::MenuCommand ({N_("By File Name")}, action_playlist_sort_selected_by_filename), + audqt::MenuCommand ({N_("By File Path")}, action_playlist_sort_selected_by_full_path), + audqt::MenuCommand ({N_("By Custom Title")}, action_playlist_sort_selected_by_custom_title) +}; + +static const audqt::MenuItem playlist_sort_items[] = { + audqt::MenuCommand ({N_("Randomize List"), nullptr, "Shift+Ctrl+R"}, action_playlist_randomize_list), + audqt::MenuCommand ({N_("Reverse List"), "view-sort-descending"}, action_playlist_reverse_list), + audqt::MenuSep (), + audqt::MenuSub ({N_("Sort Selected"), "view-sort-ascending"}, {sort_selected_items}), + audqt::MenuSub ({N_("Sort List"), "view-sort-ascending"}, {sort_items}) +}; + +static const audqt::MenuItem playlist_context_items[] = { + audqt::MenuCommand ({N_("Song Info ..."), "dialog-information", "Alt+I"}, action_playlist_track_info), + audqt::MenuSep (), +#if 0 + audqt::MenuCommand ({N_("Cut"), "edit-cut", "Ctrl+X"}, action_playlist_cut), + audqt::MenuCommand ({N_("Copy"), "edit-copy", "Ctrl+C"}, action_playlist_copy), + audqt::MenuCommand ({N_("Paste"), "edit-paste", "Ctrl+V"}, action_playlist_paste), + audqt::MenuSep (), +#endif + audqt::MenuCommand ({N_("Queue/Unqueue"), nullptr, "Q"}, action_queue_toggle), + audqt::MenuSep (), + audqt::MenuSub ({N_("Services")}, get_plugin_menu_playlist) +}; + +void menu_init (QWidget * parent) +{ + static const ArrayRef<audqt::MenuItem> table[] = { + {main_items}, + {playback_items}, + {playlist_items}, + {view_items}, + {playlist_add_items}, + {playlist_remove_items}, + {playlist_select_items}, + {playlist_sort_items}, + {playlist_context_items} + }; + + record_toggled (); + hook_associate ("enable record", record_toggled, nullptr); + + for (int i = UI_MENUS; i --; ) + menus[i] = audqt::menu_build (table[i], parent); +} + +void menu_cleanup () +{ + hook_dissociate ("enable record", record_toggled); +} + +void menu_popup (int id, int x, int y, bool leftward, bool upward) +{ + if (leftward || upward) + { + QSize size = menus[id]->sizeHint (); + if (leftward) + x -= size.width (); + if (upward) + y -= size.height (); + } + + menus[id]->popup (QPoint (x, y)); +} diff --git a/src/skins/preset-list.h b/src/skins-qt/menus.h index a1c9251..463e60d 100644 --- a/src/skins/preset-list.h +++ b/src/skins-qt/menus.h @@ -1,6 +1,6 @@ /* - * preset-list.h - * Copyright 2014 John Lindgren + * menus.h + * Copyright 2009-2014 John Lindgren * * This file is part of Audacious. * @@ -19,20 +19,27 @@ * using our public API to be a derived work. */ -#ifndef SKINS_PRESET_LIST_H -#define SKINS_PRESET_LIST_H +#ifndef SKINS_MENUS_H +#define SKINS_MENUS_H -void eq_preset_load (void); -void eq_preset_load_auto (void); -void eq_preset_save (void); -void eq_preset_save_auto (void); -void eq_preset_delete (void); -void eq_preset_delete_auto (void); +class QWidget; -void eq_preset_load_default (void); -void eq_preset_save_default (void); -void eq_preset_set_zero (void); +enum { + UI_MENU_MAIN, + UI_MENU_PLAYBACK, + UI_MENU_PLAYLIST, + UI_MENU_VIEW, + UI_MENU_PLAYLIST_ADD, + UI_MENU_PLAYLIST_REMOVE, + UI_MENU_PLAYLIST_SELECT, + UI_MENU_PLAYLIST_SORT, + UI_MENU_PLAYLIST_CONTEXT, + UI_MENUS +}; -void eq_preset_list_cleanup (void); +void menu_init (QWidget * parent); +void menu_cleanup (); -#endif /* SKINS_PRESET_LIST_H */ +void menu_popup (int id, int x, int y, bool leftward, bool upward); + +#endif /* SKINS_MENUS_H */ diff --git a/src/skins/ui_skinned_monostereo.cc b/src/skins-qt/monostereo.cc index 60d5397..66b25ac 100644 --- a/src/skins/ui_skinned_monostereo.cc +++ b/src/skins-qt/monostereo.cc @@ -25,17 +25,14 @@ * Audacious or using our public API to be a derived work. */ -#include "draw-compat.h" #include "skins_cfg.h" -#include "ui_skin.h" -#include "ui_skinned_monostereo.h" +#include "skin.h" +#include "monostereo.h" -static int monostereo_num_channels; - -DRAW_FUNC_BEGIN (monostereo_draw) - switch (monostereo_num_channels) +void MonoStereo::draw (QPainter & cr) +{ + switch (m_num_channels) { - case -1: case 0: skin_draw_pixbuf (cr, SKIN_MONOSTEREO, 29, 12, 0, 0, 27, 12); skin_draw_pixbuf (cr, SKIN_MONOSTEREO, 0, 12, 27, 0, 29, 12); @@ -49,18 +46,16 @@ DRAW_FUNC_BEGIN (monostereo_draw) skin_draw_pixbuf (cr, SKIN_MONOSTEREO, 0, 0, 27, 0, 29, 12); break; } -DRAW_FUNC_END +} -GtkWidget * ui_skinned_monostereo_new (void) +MonoStereo::MonoStereo () { - GtkWidget * monostereo = gtk_drawing_area_new (); - gtk_widget_set_size_request (monostereo, 56 * config.scale, 12 * config.scale); - DRAW_CONNECT (monostereo, monostereo_draw); - return monostereo; + set_scale (config.scale); + add_drawable (56, 12); } -void ui_skinned_monostereo_set_num_channels (GtkWidget * monostereo, int nch) +void MonoStereo::set_num_channels (int num_channels) { - monostereo_num_channels = nch; - gtk_widget_queue_draw (monostereo); + m_num_channels = num_channels; + queue_draw (); } diff --git a/src/skins-qt/monostereo.h b/src/skins-qt/monostereo.h new file mode 100644 index 0000000..2de4109 --- /dev/null +++ b/src/skins-qt/monostereo.h @@ -0,0 +1,45 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2011 John Lindgren + * + * Based on: + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#ifndef SKINS_UI_SKINNED_MONOSTEREO_H +#define SKINS_UI_SKINNED_MONOSTEREO_H + +#include "widget.h" + +class MonoStereo : public Widget +{ +public: + MonoStereo (); + void set_num_channels (int num_channels); + +private: + void draw (QPainter & cr); + + int m_num_channels = 0; +}; + +#endif diff --git a/src/skins-qt/number.cc b/src/skins-qt/number.cc new file mode 100644 index 0000000..9c34379 --- /dev/null +++ b/src/skins-qt/number.cc @@ -0,0 +1,60 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2011 John Lindgren + * + * Based on: + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include <libaudcore/runtime.h> + +#include "skins_cfg.h" +#include "main.h" +#include "skin.h" +#include "number.h" + +void SkinnedNumber::draw (QPainter & cr) +{ + skin_draw_pixbuf (cr, SKIN_NUMBERS, m_num * 9, 0, 0, 0, 9, 13); +} + +bool SkinnedNumber::button_press (QMouseEvent * event) +{ + return change_timer_mode_cb (event); +} + +SkinnedNumber::SkinnedNumber () +{ + set_scale (config.scale); + add_input (9, 13, false, true); +} + +void SkinnedNumber::set (char c) +{ + int value = (c >= '0' && c <= '9') ? c - '0' : (c == '-') ? 11 : 10; + + if (m_num != value) + { + m_num = value; + queue_draw (); + } +} diff --git a/src/skins/ui_skinned_number.h b/src/skins-qt/number.h index 3ddde4a..d9576d8 100644 --- a/src/skins/ui_skinned_number.h +++ b/src/skins-qt/number.h @@ -22,10 +22,19 @@ #ifndef SKINS_UI_SKINNED_NUMBER_H #define SKINS_UI_SKINNED_NUMBER_H -#include <gtk/gtk.h> +#include "widget.h" -GtkWidget * ui_skinned_number_new (); -void ui_skinned_number_set (GtkWidget * widget, char c); -void ui_skinned_number_set_size(GtkWidget *widget, int width, int height); +class SkinnedNumber : public Widget +{ +public: + SkinnedNumber (); + void set (char c); + +private: + virtual void draw (QPainter & cr); + virtual bool button_press (QMouseEvent * event); + + int m_num = 0; +}; #endif diff --git a/src/skins-qt/playlist-slider.cc b/src/skins-qt/playlist-slider.cc new file mode 100644 index 0000000..d2bf53c --- /dev/null +++ b/src/skins-qt/playlist-slider.cc @@ -0,0 +1,123 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2011 John Lindgren + * + * Based on: + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include <libaudcore/objects.h> +#include <libaudcore/playlist.h> + +#include "skins_cfg.h" +#include "skin.h" +#include "playlist-widget.h" +#include "playlist-slider.h" + +void PlaylistSlider::draw (QPainter & cr) +{ + int rows, first; + m_list->row_info (& rows, & first); + + int range = m_length - rows; + + int y; + if (m_length > rows) + y = (first * (m_height - 19) + range / 2) / range; + else + y = 0; + + for (int i = 0; i < m_height / 29; i ++) + skin_draw_pixbuf (cr, SKIN_PLEDIT, 36, 42, 0, 29 * i, 8, 29); + + skin_draw_pixbuf (cr, SKIN_PLEDIT, m_pressed ? 61 : 52, 53, 0, y, 8, 18); +} + +void PlaylistSlider::set_pos (int y) +{ + y = aud::clamp (y, 0, m_height - 19); + + int rows, first; + m_list->row_info (& rows, & first); + + int range = m_height - 19; + m_list->scroll_to ((y * (m_length - rows) + range / 2) / range); +} + +bool PlaylistSlider::button_press (QMouseEvent * event) +{ + if (event->button () != Qt::LeftButton) + return false; + + m_pressed = true; + set_pos (event->y () / config.scale - 9); + + queue_draw (); + return true; +} + +bool PlaylistSlider::button_release (QMouseEvent * event) +{ + if (event->button () != Qt::LeftButton) + return false; + + if (! m_pressed) + return true; + + m_pressed = false; + set_pos (event->y () / config.scale - 9); + + queue_draw (); + return true; +} + +bool PlaylistSlider::motion (QMouseEvent * event) +{ + if (! m_pressed) + return true; + + set_pos (event->y () / config.scale - 9); + + queue_draw (); + return true; +} + +PlaylistSlider::PlaylistSlider (PlaylistWidget * list, int height) : + m_list (list), m_height (height), + m_length (aud_playlist_entry_count (aud_playlist_get_active ())) +{ + set_scale (config.scale); + add_input (8, height, true, true); +} + +void PlaylistSlider::resize (int height) +{ + m_height = height; + Widget::resize (8, height); + queue_draw (); +} + +void PlaylistSlider::refresh () +{ + m_length = aud_playlist_entry_count (aud_playlist_get_active ()); + queue_draw (); +} diff --git a/src/skins/ui_skinned_textbox.h b/src/skins-qt/playlist-slider.h index 9cadea5..afd0c46 100644 --- a/src/skins/ui_skinned_textbox.h +++ b/src/skins-qt/playlist-slider.h @@ -25,19 +25,31 @@ * Audacious or using our public API to be a derived work. */ -#ifndef SKINS_UI_SKINNED_TEXTBOX_H -#define SKINS_UI_SKINNED_TEXTBOX_H +#ifndef SKINS_UI_SKINNED_PLAYLIST_SLIDER_H +#define SKINS_UI_SKINNED_PLAYLIST_SLIDER_H -#include <gtk/gtk.h> +#include "widget.h" -GtkWidget * textbox_new (int width, const char * text, const char * font, - gboolean scroll); -void textbox_set_width (GtkWidget * textbox, int width); -const char * textbox_get_text (GtkWidget * textbox); -void textbox_set_text (GtkWidget * textbox, const char * text); -void textbox_set_font (GtkWidget * textbox, const char * font); -void textbox_set_scroll (GtkWidget * textbox, gboolean scroll); +class PlaylistWidget; -void textbox_update_all (void); +class PlaylistSlider : public Widget +{ +public: + PlaylistSlider (PlaylistWidget * list, int height); + void resize (int height); + void refresh (); + +private: + void draw (QPainter & cr); + bool button_press (QMouseEvent * event); + bool button_release (QMouseEvent * event); + bool motion (QMouseEvent * event); + + void set_pos (int y); + + PlaylistWidget * m_list; + int m_height, m_length; + bool m_pressed = false; +}; #endif diff --git a/src/skins-qt/playlist-widget.cc b/src/skins-qt/playlist-widget.cc new file mode 100644 index 0000000..07b8e30 --- /dev/null +++ b/src/skins-qt/playlist-widget.cc @@ -0,0 +1,773 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2008 William Pitcock + * Copyright (c) 2009-2011 John Lindgren + * + * Based on: + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include "menus.h" +#include "skins_cfg.h" +#include "skin.h" +#include "playlist-widget.h" +#include "playlist-slider.h" + +#include <libaudcore/audstrings.h> +#include <libaudcore/hook.h> +#include <libaudcore/i18n.h> +#include <libaudcore/runtime.h> +#include <libaudcore/playlist.h> + +enum { + DRAG_SELECT = 1, + DRAG_MOVE +}; + +void PlaylistWidget::update_title () +{ + if (aud_playlist_count () > 1) + { + String title = aud_playlist_get_title (m_playlist); + m_title_text = String (str_printf (_("%s (%d of %d)"), + (const char *) title, 1 + m_playlist, aud_playlist_count ())); + } + else + m_title_text = String (); +} + +void PlaylistWidget::calc_layout () +{ + m_rows = m_height / m_row_height; + + if (m_rows && m_title_text) + { + m_offset = m_row_height; + m_rows --; + } + else + m_offset = 0; + + if (m_first + m_rows > m_length) + m_first = m_length - m_rows; + if (m_first < 0) + m_first = 0; +} + +int PlaylistWidget::calc_position (int y) const +{ + if (y < m_offset) + return -1; + + int position = m_first + (y - m_offset) / m_row_height; + if (position >= m_first + m_rows || position >= m_length) + return m_length; + + return position; +} + +int PlaylistWidget::adjust_position (bool relative, int position) const +{ + if (m_length == 0) + return -1; + + if (relative) + { + int focus = aud_playlist_get_focus (m_playlist); + if (focus == -1) + return 0; + + position += focus; + } + + if (position < 0) + return 0; + if (position >= m_length) + return m_length - 1; + + return position; +} + +void PlaylistWidget::cancel_all () +{ + m_drag = false; + + if (m_scroll) + { + m_scroll = 0; + scroll_timer.stop (); + } + + if (m_hover != -1) + { + m_hover = -1; + queue_draw (); + } + + popup_hide (); +} + +void PlaylistWidget::draw (QPainter & cr) +{ + int active_entry = aud_playlist_get_position (m_playlist); + int left = 3, right = 3; + int width; + QRect rect; + + cr.setFont (* m_font); + + /* background */ + + cr.fillRect (cr.window (), QColor (skin.colors[SKIN_PLEDIT_NORMALBG])); + + /* playlist title */ + + if (m_offset) + { + cr.setPen (QColor (skin.colors[SKIN_PLEDIT_NORMAL])); + cr.drawText (left, 0, m_width - left - right, m_row_height, + Qt::AlignCenter, (const char *) m_title_text); + } + + /* selection highlight */ + + for (int i = m_first; i < m_first + m_rows && i < m_length; i ++) + { + if (aud_playlist_entry_get_selected (m_playlist, i)) + cr.fillRect (0, m_offset + m_row_height * (i - m_first), m_width, + m_row_height, QColor (skin.colors[SKIN_PLEDIT_SELECTEDBG])); + } + + /* entry numbers */ + + if (aud_get_bool (nullptr, "show_numbers_in_pl")) + { + width = 0; + + for (int i = m_first; i < m_first + m_rows && i < m_length; i ++) + { + char buf[16]; + snprintf (buf, sizeof buf, "%d.", 1 + i); + + cr.setPen (QColor (skin.colors[(i == active_entry) ? + SKIN_PLEDIT_CURRENT : SKIN_PLEDIT_NORMAL])); + cr.drawText (left, m_offset + m_row_height * (i - m_first), + m_width - left - right, m_row_height, + Qt::AlignLeft | Qt::AlignVCenter, buf, & rect); + + width = aud::max (width, rect.width ()); + } + + left += width + 4; + } + + /* entry lengths */ + + width = 0; + + for (int i = m_first; i < m_first + m_rows && i < m_length; i ++) + { + Tuple tuple = aud_playlist_entry_get_tuple (m_playlist, i, Playlist::Guess); + int len = tuple.get_int (Tuple::Length); + if (len < 0) + continue; + + cr.setPen (QColor (skin.colors[(i == active_entry) ? + SKIN_PLEDIT_CURRENT : SKIN_PLEDIT_NORMAL])); + cr.drawText (left, m_offset + m_row_height * (i - m_first), + m_width - left - right, m_row_height, + Qt::AlignRight | Qt::AlignVCenter, + (const char *) str_format_time (len), & rect); + + width = aud::max (width, rect.width ()); + } + + right += width + 6; + + /* queue positions */ + + if (aud_playlist_queue_count (m_playlist)) + { + width = 0; + + for (int i = m_first; i < m_first + m_rows && i < m_length; i ++) + { + int pos = aud_playlist_queue_find_entry (m_playlist, i); + if (pos < 0) + continue; + + char buf[16]; + snprintf (buf, sizeof buf, "(#%d)", 1 + pos); + + cr.setPen (QColor (skin.colors[(i == active_entry) ? + SKIN_PLEDIT_CURRENT : SKIN_PLEDIT_NORMAL])); + cr.drawText (left, m_offset + m_row_height * (i - m_first), + m_width - left - right, m_row_height, + Qt::AlignRight | Qt::AlignVCenter, buf, & rect); + + width = aud::max (width, rect.width ()); + } + + right += width + 6; + } + + /* titles */ + + for (int i = m_first; i < m_first + m_rows && i < m_length; i ++) + { + Tuple tuple = aud_playlist_entry_get_tuple (m_playlist, i, Playlist::Guess); + String title = tuple.get_str (Tuple::FormattedTitle); + + cr.setPen (QColor (skin.colors[(i == active_entry) ? + SKIN_PLEDIT_CURRENT : SKIN_PLEDIT_NORMAL])); + cr.drawText (left, m_offset + m_row_height * (i - m_first), + m_width - left - right, m_row_height, + Qt::AlignLeft | Qt::AlignVCenter, (const char *) title); + } + + /* focus rectangle */ + + int focus = aud_playlist_get_focus (m_playlist); + + /* don't show rectangle if this is the only selected entry */ + if (focus >= m_first && focus <= m_first + m_rows - 1 && + (! aud_playlist_entry_get_selected (m_playlist, focus) || + aud_playlist_selected_count (m_playlist) > 1)) + { + cr.setPen (QColor (skin.colors[SKIN_PLEDIT_NORMAL])); + cr.drawRect (0, m_offset + m_row_height * (focus - m_first), m_width - 1, m_row_height - 1); + } + +#if 0 + /* hover line */ + + if (m_hover >= m_first && m_hover <= m_first + m_rows) + { + cairo_new_path (cr); + cairo_set_line_width (cr, 2); + cairo_move_to (cr, 0, m_offset + m_row_height * (m_hover - m_first)); + cairo_rel_line_to (cr, m_width, 0); + set_cairo_color (cr, skin.colors[SKIN_PLEDIT_NORMAL]); + cairo_stroke (cr); + } +#endif +} + +PlaylistWidget::PlaylistWidget (int width, int height, const char * font) : + m_width (width * config.scale), + m_height (height * config.scale) +{ + add_input (m_width, m_height, true, true); + set_font (font); /* calls refresh() */ +} + +void PlaylistWidget::resize (int width, int height) +{ + m_width = width * config.scale; + m_height = height * config.scale; + + Widget::resize (m_width, m_height); + refresh (); +} + +void PlaylistWidget::set_font (const char * font) +{ + m_font.capture (qfont_from_string (font)); + m_metrics.capture (new QFontMetrics (* m_font, this)); + m_row_height = m_metrics->height (); + refresh (); +} + +void PlaylistWidget::refresh () +{ + m_playlist = aud_playlist_get_active (); + m_length = aud_playlist_entry_count (m_playlist); + update_title (); + calc_layout (); + + int id = aud_playlist_get_unique_id (m_playlist); + if (m_playlist_id != id) + { + cancel_all (); + m_playlist_id = id; + m_first = 0; + ensure_visible (aud_playlist_get_focus (m_playlist)); + } + + queue_draw (); + + if (m_slider) + m_slider->refresh (); +} + +void PlaylistWidget::ensure_visible (int position) +{ + if (position < m_first || position >= m_first + m_rows) + m_first = position - m_rows / 2; + + calc_layout (); +} + +void PlaylistWidget::select_single (bool relative, int position) +{ + position = adjust_position (relative, position); + + if (position == -1) + return; + + aud_playlist_select_all (m_playlist, false); + aud_playlist_entry_set_selected (m_playlist, position, true); + aud_playlist_set_focus (m_playlist, position); + ensure_visible (position); +} + +void PlaylistWidget::select_extend (bool relative, int position) +{ + position = adjust_position (relative, position); + + if (position == -1) + return; + + int count = adjust_position (true, 0); + int sign = (position > count) ? 1 : -1; + + for (; count != position; count += sign) + aud_playlist_entry_set_selected (m_playlist, count, + ! aud_playlist_entry_get_selected (m_playlist, count + sign)); + + aud_playlist_entry_set_selected (m_playlist, position, true); + aud_playlist_set_focus (m_playlist, position); + ensure_visible (position); +} + +void PlaylistWidget::select_slide (bool relative, int position) +{ + position = adjust_position (relative, position); + + if (position == -1) + return; + + aud_playlist_set_focus (m_playlist, position); + ensure_visible (position); +} + +void PlaylistWidget::select_toggle (bool relative, int position) +{ + position = adjust_position (relative, position); + + if (position == -1) + return; + + aud_playlist_entry_set_selected (m_playlist, position, + ! aud_playlist_entry_get_selected (m_playlist, position)); + aud_playlist_set_focus (m_playlist, position); + ensure_visible (position); +} + +void PlaylistWidget::select_move (bool relative, int position) +{ + int focus = aud_playlist_get_focus (m_playlist); + position = adjust_position (relative, position); + + if (focus == -1 || position == -1 || position == focus) + return; + + focus += aud_playlist_shift (m_playlist, focus, position - focus); + ensure_visible (focus); +} + +void PlaylistWidget::delete_selected () +{ + aud_playlist_delete_selected (m_playlist); + + m_length = aud_playlist_entry_count (m_playlist); + int focus = aud_playlist_get_focus (m_playlist); + + if (focus != -1) + { + aud_playlist_entry_set_selected (m_playlist, focus, true); + ensure_visible (focus); + } +} + +bool PlaylistWidget::handle_keypress (QKeyEvent * event) +{ + cancel_all (); + + switch (event->modifiers () & (Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier)) + { + case 0: + switch (event->key ()) + { + case Qt::Key_Up: + select_single (true, -1); + break; + case Qt::Key_Down: + select_single (true, 1); + break; + case Qt::Key_PageUp: + select_single (true, -m_rows); + break; + case Qt::Key_PageDown: + select_single (true, m_rows); + break; + case Qt::Key_Home: + select_single (false, 0); + break; + case Qt::Key_End: + select_single (false, m_length - 1); + break; + case Qt::Key_Return: + select_single (true, 0); + aud_playlist_set_position (m_playlist, aud_playlist_get_focus (m_playlist)); + aud_playlist_play (m_playlist); + break; + case Qt::Key_Escape: + select_single (false, aud_playlist_get_position (m_playlist)); + break; + case Qt::Key_Delete: + delete_selected (); + break; + default: + return false; + } + break; + case Qt::ShiftModifier: + switch (event->key ()) + { + case Qt::Key_Up: + select_extend (true, -1); + break; + case Qt::Key_Down: + select_extend (true, 1); + break; + case Qt::Key_PageUp: + select_extend (true, -m_rows); + break; + case Qt::Key_PageDown: + select_extend (true, m_rows); + break; + case Qt::Key_Home: + select_extend (false, 0); + break; + case Qt::Key_End: + select_extend (false, m_length - 1); + break; + default: + return false; + } + break; + case Qt::ControlModifier: + switch (event->key ()) + { + case Qt::Key_Space: + select_toggle (true, 0); + break; + case Qt::Key_Up: + select_slide (true, -1); + break; + case Qt::Key_Down: + select_slide (true, 1); + break; + case Qt::Key_PageUp: + select_slide (true, -m_rows); + break; + case Qt::Key_PageDown: + select_slide (true, m_rows); + break; + case Qt::Key_Home: + select_slide (false, 0); + break; + case Qt::Key_End: + select_slide (false, m_length - 1); + break; + default: + return false; + } + break; + case Qt::AltModifier: + switch (event->key ()) + { + case Qt::Key_Up: + select_move (true, -1); + break; + case Qt::Key_Down: + select_move (true, 1); + break; + case Qt::Key_PageUp: + select_move (true, -m_rows); + break; + case Qt::Key_PageDown: + select_move (true, m_rows); + break; + case Qt::Key_Home: + select_move (false, 0); + break; + case Qt::Key_End: + select_move (false, m_length - 1); + break; + default: + return false; + } + break; + default: + return false; + } + + refresh (); + return true; +} + +void PlaylistWidget::row_info (int * rows, int * first) +{ + * rows = m_rows; + * first = m_first; +} + +void PlaylistWidget::scroll_to (int row) +{ + cancel_all (); + m_first = row; + refresh (); +} + +void PlaylistWidget::set_focused (int row) +{ + cancel_all (); + aud_playlist_set_focus (m_playlist, row); + ensure_visible (row); + refresh (); +} + +void PlaylistWidget::hover (int x, int y) +{ + int row; + + if (y < m_offset) + row = m_first; + else if (y > m_offset + m_row_height * m_rows) + row = m_first + m_rows; + else + row = m_first + (y - m_offset + m_row_height / 2) / m_row_height; + + if (row > m_length) + row = m_length; + + if (row != m_hover) + { + m_hover = row; + queue_draw (); + } +} + +int PlaylistWidget::hover_end () +{ + int temp = m_hover; + m_hover = -1; + + queue_draw (); + return temp; +} + +bool PlaylistWidget::button_press (QMouseEvent * event) +{ + int position = calc_position (event->y ()); + int state = event->modifiers () & (Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier); + + cancel_all (); + + switch (event->type ()) + { + case QEvent::MouseButtonPress: + switch (event->button ()) + { + case Qt::LeftButton: + if (position == -1 || position == m_length) + return true; + + switch (state) + { + case 0: + if (aud_playlist_entry_get_selected (m_playlist, position)) + select_slide (false, position); + else + select_single (false, position); + + m_drag = DRAG_MOVE; + break; + case Qt::ShiftModifier: + select_extend (false, position); + m_drag = DRAG_SELECT; + break; + case Qt::ControlModifier: + select_toggle (false, position); + m_drag = DRAG_SELECT; + break; + default: + return true; + } + + break; + case Qt::RightButton: + if (state) + return true; + + if (position != -1 && position != m_length) + { + if (aud_playlist_entry_get_selected (m_playlist, position)) + select_slide (false, position); + else + select_single (false, position); + } + + menu_popup ((position == -1) ? UI_MENU_PLAYLIST : + UI_MENU_PLAYLIST_CONTEXT, event->globalX (), event->globalY (), + false, false); + break; + default: + return false; + } + + break; + case QEvent::MouseButtonDblClick: + if (event->button () != Qt::LeftButton || state || position == m_length) + return true; + + if (position != -1) + aud_playlist_set_position (m_playlist, position); + + aud_playlist_play (m_playlist); + break; + default: + return true; + } + + refresh (); + return true; +} + +bool PlaylistWidget::button_release (QMouseEvent * event) +{ + cancel_all (); + return true; +} + +void PlaylistWidget::scroll_timeout () +{ + int position = adjust_position (true, m_scroll); + if (position == -1) + return; + + switch (m_drag) + { + case DRAG_SELECT: + select_extend (false, position); + break; + case DRAG_MOVE: + select_move (false, position); + break; + } + + refresh (); +} + +bool PlaylistWidget::motion (QMouseEvent * event) +{ + int position = calc_position (event->y ()); + + if (m_drag) + { + if (position == -1 || position == m_length) + { + if (! m_scroll) + scroll_timer.start (); + + m_scroll = (position == -1 ? -1 : 1); + } + else + { + if (m_scroll) + { + m_scroll = 0; + scroll_timer.stop (); + } + + switch (m_drag) + { + case DRAG_SELECT: + select_extend (false, position); + break; + case DRAG_MOVE: + select_move (false, position); + break; + } + + refresh (); + } + } + else + { + if (position == -1 || position == m_length) + cancel_all (); + else if (aud_get_bool (nullptr, "show_filepopup_for_tuple") && m_popup_pos != position) + { + cancel_all (); + popup_trigger (position); + } + } + + return true; +} + +bool PlaylistWidget::leave () +{ + if (! m_drag) + cancel_all (); + + return true; +} + +void PlaylistWidget::popup_trigger (int pos) +{ +#if 0 + audgui_infopopup_hide (); + + auto show_cb = [] (void * me_) { + auto me = (PlaylistWidget *) me_; + audgui_infopopup_show (me->m_playlist, me->m_popup_pos); + }; + + m_popup_pos = pos; + m_popup_timer.queue (aud_get_int (nullptr, "filepopup_delay") * 100, show_cb, this); +#endif +} + +void PlaylistWidget::popup_hide () +{ +#if 0 + audgui_infopopup_hide (); + + m_popup_pos = -1; + m_popup_timer.stop (); +#endif +} diff --git a/src/skins-qt/playlist-widget.h b/src/skins-qt/playlist-widget.h new file mode 100644 index 0000000..4167be5 --- /dev/null +++ b/src/skins-qt/playlist-widget.h @@ -0,0 +1,98 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2009-2011 John Lindgren + * + * Based on: + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#ifndef SKINS_UI_SKINNED_PLAYLIST_H +#define SKINS_UI_SKINNED_PLAYLIST_H + +#include <libaudcore/hook.h> +#include <libaudcore/mainloop.h> +#include <libaudcore/objects.h> + +#include "widget.h" + +class PlaylistSlider; +class QFont; +class QFontMetrics; + +class PlaylistWidget : public Widget +{ +public: + PlaylistWidget (int width, int height, const char * font); + ~PlaylistWidget () { cancel_all (); } + + void set_slider (PlaylistSlider * slider) { m_slider = slider; } + void resize (int width, int height); + void set_font (const char * m_font); + void refresh (); + bool handle_keypress (QKeyEvent * event); + void row_info (int * m_rows, int * m_first); + void scroll_to (int row); + void set_focused (int row); + void hover (int x, int y); + int hover_end (); + +private: + void draw (QPainter & cr); + bool button_press (QMouseEvent * event); + bool button_release (QMouseEvent * event); + bool motion (QMouseEvent * event); + bool leave (); + + void update_title (); + void calc_layout (); + + int calc_position (int y) const; + int adjust_position (bool relative, int position) const; + + void ensure_visible (int position); + void select_single (bool relative, int position); + void select_extend (bool relative, int position); + void select_slide (bool relative, int position); + void select_toggle (bool relative, int position); + void select_move (bool relative, int position); + void delete_selected (); + + void cancel_all (); + void scroll_timeout (); + void popup_trigger (int pos); + void popup_hide (); + + const Timer<PlaylistWidget> + scroll_timer {TimerRate::Hz10, this, & PlaylistWidget::scroll_timeout}; + + PlaylistSlider * m_slider = nullptr; + SmartPtr<QFont> m_font; + SmartPtr<QFontMetrics> m_metrics; + String m_title_text; + + int m_playlist = -1, m_playlist_id = -1, m_length = 0; + int m_width = 0, m_height = 0, m_row_height = 1, m_offset = 0, m_rows = 0, m_first = 0; + int m_scroll = 0, m_hover = -1, m_drag = 0, m_popup_pos = -1; + QueuedFunc m_popup_timer; +}; + +#endif diff --git a/src/skins-qt/playlist.cc b/src/skins-qt/playlist.cc new file mode 100644 index 0000000..5cb7bac --- /dev/null +++ b/src/skins-qt/playlist.cc @@ -0,0 +1,538 @@ +/* Audacious - Cross-platform multimedia player + * Copyright (C) 2005-2011 Audacious development team. + * + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include <inttypes.h> +#include <string.h> + +#include <libaudcore/audstrings.h> +#include <libaudcore/drct.h> +#include <libaudcore/hook.h> +#include <libaudcore/i18n.h> +#include <libaudcore/playlist.h> +#include <libaudcore/runtime.h> +#include <libaudcore/tuple.h> + +#include "actions-mainwin.h" +#include "dnd.h" +#include "drag-handle.h" +#include "menus.h" +#include "plugin.h" +#include "skins_cfg.h" +#include "main.h" +#include "playlist.h" +#include "button.h" +#include "playlist-widget.h" +#include "playlist-slider.h" +#include "textbox.h" +#include "window.h" +#include "view.h" + +#define PLAYLISTWIN_MIN_WIDTH MAINWIN_WIDTH +#define PLAYLISTWIN_MIN_HEIGHT MAINWIN_HEIGHT +#define PLAYLISTWIN_WIDTH_SNAP 25 +#define PLAYLISTWIN_HEIGHT_SNAP 29 +#define PLAYLISTWIN_SHADED_HEIGHT MAINWIN_SHADED_HEIGHT + +#define APPEND(b, ...) snprintf (b + strlen (b), sizeof b - strlen (b), __VA_ARGS__) + +class PlWindow : public Window +{ +public: + PlWindow (bool shaded) : + Window (WINDOW_PLAYLIST, & config.playlist_x, & config.playlist_y, + config.playlist_width, shaded ? PLAYLISTWIN_SHADED_HEIGHT : + config.playlist_height, shaded) {} + +private: + void draw (QPainter & cr); + bool button_press (QMouseEvent * event); + bool scroll (QWheelEvent * event); +}; + +Window * playlistwin; +PlaylistWidget * playlistwin_list; +TextBox * playlistwin_sinfo; + +static Button * playlistwin_shade, * playlistwin_close; +static Button * playlistwin_shaded_shade, * playlistwin_shaded_close; + +static PlaylistSlider * playlistwin_slider; +static TextBox * playlistwin_time_min, * playlistwin_time_sec; +static TextBox * playlistwin_info; +static Button * playlistwin_srew, * playlistwin_splay; +static Button * playlistwin_spause, * playlistwin_sstop; +static Button * playlistwin_sfwd, * playlistwin_seject; +static Button * playlistwin_sscroll_up, *playlistwin_sscroll_down; +static DragHandle * resize_handle, * sresize_handle; +static Button * button_add, * button_sub, * button_sel, * button_misc, * button_list; + +static int resize_base_width, resize_base_height; +//static int drop_position; +static bool song_changed; + +static void update_info () +{ + int playlist = aud_playlist_get_active (); + StringBuf s1 = str_format_time (aud_playlist_get_selected_length (playlist)); + StringBuf s2 = str_format_time (aud_playlist_get_total_length (playlist)); + playlistwin_info->set_text (str_concat ({s1, "/", s2})); +} + +static void update_rollup_text () +{ + int playlist = aud_playlist_get_active (); + int entry = aud_playlist_get_position (playlist); + Tuple tuple = aud_playlist_entry_get_tuple (playlist, entry, Playlist::Guess); + char scratch[512]; + + scratch[0] = 0; + + if (entry > -1) + { + String title = tuple.get_str (Tuple::FormattedTitle); + int length = tuple.get_int (Tuple::Length); + + if (aud_get_bool (nullptr, "show_numbers_in_pl")) + APPEND (scratch, "%d. ", 1 + entry); + + APPEND (scratch, "%s", (const char *) title); + + if (length >= 0) + { + StringBuf buf = str_format_time (length); + APPEND (scratch, " (%s)", (const char *) buf); + } + } + + playlistwin_sinfo->set_text (scratch); +} + +static void playlistwin_shade_toggle () +{ + view_set_playlist_shaded (! aud_get_bool ("skins", "playlist_shaded")); +} + +static void playlistwin_scroll (float dir) +{ + int rows, first; + + playlistwin_list->row_info (& rows, & first); + playlistwin_list->scroll_to (first + (int) (dir * rows / 3)); +} + +static void playlistwin_scroll_up_pushed () +{ + playlistwin_scroll (-1); +} + +static void playlistwin_scroll_down_pushed () +{ + playlistwin_scroll (1); +} + +/* note: height is ignored if the window is shaded */ +static void playlistwin_resize (int w, int h) +{ + int tx, ty; + + tx = (w - PLAYLISTWIN_MIN_WIDTH) / PLAYLISTWIN_WIDTH_SNAP; + tx = (tx * PLAYLISTWIN_WIDTH_SNAP) + PLAYLISTWIN_MIN_WIDTH; + if (tx < PLAYLISTWIN_MIN_WIDTH) + tx = PLAYLISTWIN_MIN_WIDTH; + + if (! aud_get_bool ("skins", "playlist_shaded")) + { + ty = (h - PLAYLISTWIN_MIN_HEIGHT) / PLAYLISTWIN_HEIGHT_SNAP; + ty = (ty * PLAYLISTWIN_HEIGHT_SNAP) + PLAYLISTWIN_MIN_HEIGHT; + if (ty < PLAYLISTWIN_MIN_HEIGHT) + ty = PLAYLISTWIN_MIN_HEIGHT; + } + else + ty = config.playlist_height; + + if (tx == config.playlist_width && ty == config.playlist_height) + return; + + config.playlist_width = w = tx; + config.playlist_height = h = ty; + + playlistwin_list->resize (w - 31, h - 58); + playlistwin->move_widget (false, playlistwin_slider, w - 15, 20); + playlistwin_slider->resize (h - 58); + + playlistwin->move_widget (true, playlistwin_shaded_shade, w - 21, 3); + playlistwin->move_widget (true, playlistwin_shaded_close, w - 11, 3); + playlistwin->move_widget (false, playlistwin_shade, w - 21, 3); + playlistwin->move_widget (false, playlistwin_close, w - 11, 3); + + playlistwin->move_widget (false, playlistwin_time_min, w - 82, h - 15); + playlistwin->move_widget (false, playlistwin_time_sec, w - 64, h - 15); + playlistwin->move_widget (false, playlistwin_info, w - 143, h - 28); + + playlistwin->move_widget (false, playlistwin_srew, w - 144, h - 16); + playlistwin->move_widget (false, playlistwin_splay, w - 138, h - 16); + playlistwin->move_widget (false, playlistwin_spause, w - 128, h - 16); + playlistwin->move_widget (false, playlistwin_sstop, w - 118, h - 16); + playlistwin->move_widget (false, playlistwin_sfwd, w - 109, h - 16); + playlistwin->move_widget (false, playlistwin_seject, w - 100, h - 16); + playlistwin->move_widget (false, playlistwin_sscroll_up, w - 14, h - 35); + playlistwin->move_widget (false, playlistwin_sscroll_down, w - 14, h - 30); + + playlistwin->move_widget (false, resize_handle, w - 20, h - 20); + playlistwin->move_widget (true, sresize_handle, w - 31, 0); + + playlistwin_sinfo->set_width (w - 35); + + playlistwin->move_widget (false, button_add, 12, h - 29); + playlistwin->move_widget (false, button_sub, 40, h - 29); + playlistwin->move_widget (false, button_sel, 68, h - 29); + playlistwin->move_widget (false, button_misc, 100, h - 29); + playlistwin->move_widget (false, button_list, w - 46, h - 29); +} + +bool PlWindow::scroll (QWheelEvent * event) +{ + float delta = -event->angleDelta ().y () / 120.0f; + if (delta) + playlistwin_scroll (delta); + + return true; +} + +bool PlWindow::button_press (QMouseEvent * event) +{ + if (event->button () == Qt::LeftButton && + event->type () == QEvent::MouseButtonDblClick && event->y () < 14) + { + playlistwin_shade_toggle (); + return true; + } + + if (event->button () == Qt::RightButton && event->type () == QEvent::MouseButtonPress) + { + menu_popup (UI_MENU_PLAYLIST, event->globalX (), event->globalY (), false, false); + return true; + } + + return Window::button_press (event); +} + +void playlistwin_hide_timer () +{ + playlistwin_time_min->set_text (nullptr); + playlistwin_time_sec->set_text (nullptr); +} + +void playlistwin_set_time (const char * minutes, const char * seconds) +{ + playlistwin_time_min->set_text (minutes); + playlistwin_time_sec->set_text (seconds); +} + +#if 0 +static void drag_motion (GtkWidget * widget, GdkDragContext * context, int x, + int y, unsigned time, void * unused) +{ + if (! aud_get_bool ("skins", "playlist_shaded")) + playlistwin_list->hover (x - 12, y - 20); +} + +static void drag_leave (GtkWidget * widget, GdkDragContext * context, unsigned time, + void * unused) +{ + if (! aud_get_bool ("skins", "playlist_shaded")) + playlistwin_list->hover_end (); +} + +static void drag_drop (GtkWidget * widget, GdkDragContext * context, int x, + int y, unsigned time, void * unused) +{ + if (aud_get_bool ("skins", "playlist_shaded")) + drop_position = -1; + else + { + playlistwin_list->hover (x - 12, y - 20); + drop_position = playlistwin_list->hover_end (); + } +} + +static void drag_data_received (GtkWidget * widget, GdkDragContext * context, + int x, int y, GtkSelectionData * data, unsigned info, unsigned time, void * unused) +{ + audgui_urilist_insert (aud_playlist_get_active (), drop_position, + (const char *) gtk_selection_data_get_data (data)); + drop_position = -1; +} +#endif + +static void playlistwin_hide () +{ + view_set_show_playlist (false); +} + +static void resize_press () +{ + resize_base_width = config.playlist_width; + resize_base_height = config.playlist_height; +} + +static void resize_drag (int x_offset, int y_offset) +{ + bool shaded = aud_get_bool ("skins", "playlist_shaded"); + + /* compromise between rounding and truncating; this has no real + * justification at all other than it "looks about right". */ + playlistwin_resize (resize_base_width + x_offset + PLAYLISTWIN_WIDTH_SNAP / + 3, resize_base_height + y_offset + PLAYLISTWIN_HEIGHT_SNAP / 3); + playlistwin->resize (config.playlist_width, shaded ? + PLAYLISTWIN_SHADED_HEIGHT : config.playlist_height); +} + +static void button_add_cb (Button * button, QMouseEvent * event) +{ + int xpos, ypos; + playlistwin->getPosition (& xpos, & ypos); + menu_popup (UI_MENU_PLAYLIST_ADD, xpos + 12 * config.scale, + ypos + (config.playlist_height - 8) * config.scale, false, true); +} + +static void button_sub_cb (Button * button, QMouseEvent * event) +{ + int xpos, ypos; + playlistwin->getPosition (& xpos, & ypos); + menu_popup (UI_MENU_PLAYLIST_REMOVE, xpos + 40 * config.scale, + ypos + (config.playlist_height - 8) * config.scale, false, true); +} + +static void button_sel_cb (Button * button, QMouseEvent * event) +{ + int xpos, ypos; + playlistwin->getPosition (& xpos, & ypos); + menu_popup (UI_MENU_PLAYLIST_SELECT, xpos + 68 * config.scale, + ypos + (config.playlist_height - 8) * config.scale, false, true); +} + +static void button_misc_cb (Button * button, QMouseEvent * event) +{ + int xpos, ypos; + playlistwin->getPosition (& xpos, & ypos); + menu_popup (UI_MENU_PLAYLIST_SORT, xpos + 100 * config.scale, + ypos + (config.playlist_height - 8) * config.scale, false, true); +} + +static void button_list_cb (Button * button, QMouseEvent * event) +{ + int xpos, ypos; + playlistwin->getPosition (& xpos, & ypos); + menu_popup (UI_MENU_PLAYLIST, + xpos + (config.playlist_width - 12) * config.scale, + ypos + (config.playlist_height - 8) * config.scale, true, true); +} + +static void playlistwin_create_widgets () +{ + int w = config.playlist_width, h = config.playlist_height; + + bool shaded = aud_get_bool ("skins", "playlist_shaded"); + playlistwin_sinfo = new TextBox (w - 35, nullptr, shaded && config.autoscroll); + playlistwin->put_widget (true, playlistwin_sinfo, 4, 4); + + playlistwin_shaded_shade = new Button (9, 9, 128, 45, 150, 42, SKIN_PLEDIT, SKIN_PLEDIT); + playlistwin->put_widget (true, playlistwin_shaded_shade, w - 21, 3); + playlistwin_shaded_shade->on_release ((ButtonCB) playlistwin_shade_toggle); + + playlistwin_shaded_close = new Button (9, 9, 138, 45, 52, 42, SKIN_PLEDIT, SKIN_PLEDIT); + playlistwin->put_widget (true, playlistwin_shaded_close, w - 11, 3); + playlistwin_shaded_close->on_release ((ButtonCB) playlistwin_hide); + + playlistwin_shade = new Button (9, 9, 157, 3, 62, 42, SKIN_PLEDIT, SKIN_PLEDIT); + playlistwin->put_widget (false, playlistwin_shade, w - 21, 3); + playlistwin_shade->on_release ((ButtonCB) playlistwin_shade_toggle); + + playlistwin_close = new Button (9, 9, 167, 3, 52, 42, SKIN_PLEDIT, SKIN_PLEDIT); + playlistwin->put_widget (false, playlistwin_close, w - 11, 3); + playlistwin_close->on_release ((ButtonCB) playlistwin_hide); + + String font = aud_get_str ("skins", "playlist_font"); + playlistwin_list = new PlaylistWidget (w - 31, h - 58, font); + playlistwin->put_widget (false, playlistwin_list, 12, 20); + + /* playlist list box slider */ + playlistwin_slider = new PlaylistSlider (playlistwin_list, h - 58); + playlistwin->put_widget (false, playlistwin_slider, w - 15, 20); + playlistwin_list->set_slider (playlistwin_slider); + + playlistwin_time_min = new TextBox (15, nullptr, false); + playlistwin->put_widget (false, playlistwin_time_min, w - 82, h - 15); + playlistwin_time_min->on_press (change_timer_mode_cb); + + playlistwin_time_sec = new TextBox (10, nullptr, false); + playlistwin->put_widget (false, playlistwin_time_sec, w - 64, h - 15); + playlistwin_time_sec->on_press (change_timer_mode_cb); + + playlistwin_info = new TextBox (90, nullptr, false); + playlistwin->put_widget (false, playlistwin_info, w - 143, h - 28); + + /* mini play control buttons at right bottom corner */ + + playlistwin_srew = new Button (8, 7); + playlistwin->put_widget (false, playlistwin_srew, w - 144, h - 16); + playlistwin_srew->on_release ((ButtonCB) aud_drct_pl_prev); + + playlistwin_splay = new Button (10, 7); + playlistwin->put_widget (false, playlistwin_splay, w - 138, h - 16); + playlistwin_splay->on_release ((ButtonCB) aud_drct_play); + + playlistwin_spause = new Button (10, 7); + playlistwin->put_widget (false, playlistwin_spause, w - 128, h - 16); + playlistwin_spause->on_release ((ButtonCB) aud_drct_pause); + + playlistwin_sstop = new Button (9, 7); + playlistwin->put_widget (false, playlistwin_sstop, w - 118, h - 16); + playlistwin_sstop->on_release ((ButtonCB) aud_drct_stop); + + playlistwin_sfwd = new Button (8, 7); + playlistwin->put_widget (false, playlistwin_sfwd, w - 109, h - 16); + playlistwin_sfwd->on_release ((ButtonCB) aud_drct_pl_next); + + playlistwin_seject = new Button (9, 7); + playlistwin->put_widget (false, playlistwin_seject, w - 100, h - 16); + playlistwin_seject->on_release ((ButtonCB) action_play_file); + + playlistwin_sscroll_up = new Button (8, 5); + playlistwin->put_widget (false, playlistwin_sscroll_up, w - 14, h - 35); + playlistwin_sscroll_up->on_release ((ButtonCB) playlistwin_scroll_up_pushed); + + playlistwin_sscroll_down = new Button (8, 5); + playlistwin->put_widget (false, playlistwin_sscroll_down, w - 14, h - 30); + playlistwin_sscroll_down->on_release ((ButtonCB) playlistwin_scroll_down_pushed); + + /* resize handles */ + + resize_handle = new DragHandle (20, 20, resize_press, resize_drag); + playlistwin->put_widget (false, resize_handle, w - 20, h - 20); + + sresize_handle = new DragHandle (9, PLAYLISTWIN_SHADED_HEIGHT, resize_press, resize_drag); + playlistwin->put_widget (true, sresize_handle, w - 31, 0); + + /* lower button row */ + + button_add = new Button (25, 18); + playlistwin->put_widget (false, button_add, 12, h - 29); + button_add->on_press (button_add_cb); + + button_sub = new Button (25, 18); + playlistwin->put_widget (false, button_sub, 40, h - 29); + button_sub->on_press (button_sub_cb); + + button_sel = new Button (25, 18); + playlistwin->put_widget (false, button_sel, 68, h - 29); + button_sel->on_press (button_sel_cb); + + button_misc = new Button (25, 18); + playlistwin->put_widget (false, button_misc, 100, h - 29); + button_misc->on_press (button_misc_cb); + + button_list = new Button (23, 18); + playlistwin->put_widget (false, button_list, w - 46, h - 29); + button_list->on_press (button_list_cb); +} + +void PlWindow::draw (QPainter & cr) +{ + if (is_shaded ()) + skin_draw_playlistwin_shaded (cr, config.playlist_width, true); + else + skin_draw_playlistwin_frame (cr, config.playlist_width, + config.playlist_height, true); +} + +static void playlistwin_create_window () +{ + bool shaded = aud_get_bool ("skins", "playlist_shaded"); + + playlistwin = new PlWindow (shaded); + playlistwin->setWindowTitle (_("Audacious Playlist Editor")); + +#if 0 + GtkWidget * w = playlistwin->gtk (); + drag_dest_set (w); + drop_position = -1; + + g_signal_connect (w, "drag-motion", (GCallback) drag_motion, nullptr); + g_signal_connect (w, "drag-leave", (GCallback) drag_leave, nullptr); + g_signal_connect (w, "drag-drop", (GCallback) drag_drop, nullptr); + g_signal_connect (w, "drag-data-received", (GCallback) drag_data_received, nullptr); +#endif +} + +static void update_cb (void *, void *) +{ + playlistwin_list->refresh (); + + if (song_changed) + { + playlistwin_list->set_focused (aud_playlist_get_position (aud_playlist_get_active ())); + song_changed = false; + } + + update_info (); + update_rollup_text (); +} + +static void follow_cb (void * data, void *) +{ + int list = aud::from_ptr<int> (data); + aud_playlist_select_all (list, false); + + int row = aud_playlist_get_position (list); + if (row >= 0) + aud_playlist_entry_set_selected (list, row, true); + + if (list == aud_playlist_get_active ()) + song_changed = true; +} + +void playlistwin_create () +{ + playlistwin_create_window (); + playlistwin_create_widgets (); + + update_info (); + update_rollup_text (); + + song_changed = false; + + hook_associate ("playlist position", follow_cb, nullptr); + hook_associate ("playlist activate", update_cb, nullptr); + hook_associate ("playlist update", update_cb, nullptr); +} + +void playlistwin_unhook () +{ + hook_dissociate ("playlist position", follow_cb); + hook_dissociate ("playlist activate", update_cb); + hook_dissociate ("playlist update", update_cb); +} diff --git a/src/skins/ui_playlist.h b/src/skins-qt/playlist.h index 8d5754a..3f224a2 100644 --- a/src/skins/ui_playlist.h +++ b/src/skins-qt/playlist.h @@ -23,16 +23,17 @@ #ifndef SKINS_UI_PLAYLIST_H #define SKINS_UI_PLAYLIST_H -#include <gtk/gtk.h> +class PlaylistWidget; +class TextBox; +class Window; -void playlistwin_update (void); -void playlistwin_create(void); -void playlistwin_unhook (void); -void playlistwin_hide_timer(void); +void playlistwin_create (); +void playlistwin_unhook (); +void playlistwin_hide_timer (); void playlistwin_set_time (const char * minutes, const char * seconds); -extern int active_playlist, active_length; -extern char * active_title; -extern GtkWidget * playlistwin, * playlistwin_list, * playlistwin_sinfo; +extern Window * playlistwin; +extern PlaylistWidget * playlistwin_list; +extern TextBox * playlistwin_sinfo; #endif /* SKINS_UI_PLAYLIST_H */ diff --git a/src/skins-qt/playstatus.cc b/src/skins-qt/playstatus.cc new file mode 100644 index 0000000..b2c1097 --- /dev/null +++ b/src/skins-qt/playstatus.cc @@ -0,0 +1,63 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2011 John Lindgren + * + * Based on: + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include "skins_cfg.h" +#include "skin.h" +#include "playstatus.h" + +void PlayStatus::draw (QPainter & cr) +{ + if (m_status == STATUS_PLAY) + skin_draw_pixbuf (cr, SKIN_PLAYPAUSE, 36, 0, 0, 0, 3, 9); + else + skin_draw_pixbuf (cr, SKIN_PLAYPAUSE, 27, 0, 0, 0, 2, 9); + + switch (m_status) + { + case STATUS_STOP: + skin_draw_pixbuf (cr, SKIN_PLAYPAUSE, 18, 0, 2, 0, 9, 9); + break; + case STATUS_PAUSE: + skin_draw_pixbuf (cr, SKIN_PLAYPAUSE, 9, 0, 2, 0, 9, 9); + break; + case STATUS_PLAY: + skin_draw_pixbuf (cr, SKIN_PLAYPAUSE, 1, 0, 3, 0, 8, 9); + break; + } +} + +PlayStatus::PlayStatus () +{ + set_scale (config.scale); + add_drawable (11, 9); +} + +void PlayStatus::set_status (PStatus status) +{ + m_status = status; + queue_draw (); +} diff --git a/src/skins/ui_skinned_playstatus.h b/src/skins-qt/playstatus.h index ffa8c46..2d58f0b 100644 --- a/src/skins/ui_skinned_playstatus.h +++ b/src/skins-qt/playstatus.h @@ -28,14 +28,24 @@ #ifndef SKINS_UI_SKINNED_PLAYSTATUS_H #define SKINS_UI_SKINNED_PLAYSTATUS_H -#include <gtk/gtk.h> +#include "widget.h" typedef enum { - STATUS_STOP, STATUS_PAUSE, STATUS_PLAY + STATUS_STOP, + STATUS_PAUSE, + STATUS_PLAY } PStatus; -GtkWidget * ui_skinned_playstatus_new (void); -void ui_skinned_playstatus_set_status(GtkWidget *widget, PStatus status); -void ui_skinned_playstatus_set_size(GtkWidget *widget, int width, int height); +class PlayStatus : public Widget +{ +public: + PlayStatus (); + void set_status (PStatus status); + +private: + void draw (QPainter & cr); + + PStatus m_status = STATUS_STOP; +}; #endif diff --git a/src/skins-qt/plugin-window.cc b/src/skins-qt/plugin-window.cc new file mode 100644 index 0000000..8b19b65 --- /dev/null +++ b/src/skins-qt/plugin-window.cc @@ -0,0 +1,208 @@ +/* + * plugin-window.c + * Copyright 2014 John Lindgren + * + * This file is part of Audacious. + * + * Audacious 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, version 2 or version 3 of the License. + * + * Audacious 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 + * Audacious. If not, see <http://www.gnu.org/licenses/>. + * + * The Audacious team does not consider modular code linking to Audacious or + * using our public API to be a derived work. + */ + +/* TODO (someday): implement proper docking for plugin windows */ + +#include "plugin-window.h" + +#include <QVBoxLayout> +#include <QWidget> +#include <QWindow> + +#include <libaudcore/audstrings.h> +#include <libaudcore/interface.h> +#include <libaudcore/plugin.h> +#include <libaudcore/plugins.h> +#include <libaudcore/hook.h> +#include <libaudcore/runtime.h> + +#include "main.h" +#include "window.h" + +class PluginWindow : public QWidget +{ +public: + PluginWindow (PluginHandle * plugin, QWidget * widget) : + m_plugin (plugin), + m_widget (widget) + { + setWindowFlags (Qt::Dialog); + setWindowTitle (aud_plugin_get_name (plugin)); + + const char * basename = aud_plugin_get_basename (plugin); + String pos_str = aud_get_str ("skins-layout", basename); + int pos[4]; + + if (pos_str && str_to_int_array (pos_str, pos, 4)) + { + move (pos[0], pos[1]); + resize (pos[2], pos[3]); + } + else + resize (320, 240); + + auto vbox = new QVBoxLayout (this); + vbox->setContentsMargins (2, 2, 2, 2); + vbox->addWidget (widget); + } + + PluginHandle * plugin () const { return m_plugin; } + QWidget * widget () const { return m_widget; } + + void show () + { + winId (); + windowHandle ()->setTransientParent (mainwin->windowHandle ()); + QWidget::show (); + } + + void save_size () + { + if (! isVisible ()) + return; + + const char * basename = aud_plugin_get_basename (m_plugin); + int pos[4] = {x (), y (), width (), height ()}; + aud_set_str ("skins-layout", basename, int_array_to_str (pos, 4)); + } + +protected: + void closeEvent (QCloseEvent * event) + { + aud_plugin_enable (m_plugin, false); + event->ignore (); + } + + void keyPressEvent (QKeyEvent * event) + { + if (event->key () == Qt::Key_Escape) + { + aud_plugin_enable (m_plugin, false); + event->accept (); + } + } + +private: + PluginHandle * m_plugin; + QWidget * m_widget; +}; + +static Index<PluginWindow *> windows; + +static void add_dock_plugin (PluginHandle * plugin, void *) +{ + auto widget = (QWidget *) aud_plugin_get_qt_widget (plugin); + + if (widget) + { + auto window = new PluginWindow (plugin, widget); + windows.append (window); + + if (aud_ui_is_shown ()) + window->show (); + } +} + +static int find_dock_plugin (PluginHandle * plugin) +{ + int count = windows.len (); + for (int i = 0; i < count; i ++) + { + if (windows[i]->plugin () == plugin) + return i; + } + + return -1; +} + +static void remove_dock_plugin (PluginHandle * plugin, void * unused) +{ + int idx = find_dock_plugin (plugin); + if (idx < 0) + return; + + auto window = windows[idx]; + windows.remove (idx, 1); + + window->save_size (); + delete window->widget (); + window->deleteLater (); +} + +void create_plugin_windows () +{ + for (PluginHandle * plugin : aud_plugin_list (PluginType::General)) + { + if (aud_plugin_get_enabled (plugin)) + add_dock_plugin (plugin, nullptr); + } + + for (PluginHandle * plugin : aud_plugin_list (PluginType::Vis)) + { + if (aud_plugin_get_enabled (plugin)) + add_dock_plugin (plugin, nullptr); + } + + hook_associate ("dock plugin enabled", (HookFunction) add_dock_plugin, nullptr); + hook_associate ("dock plugin disabled", (HookFunction) remove_dock_plugin, nullptr); +} + +void show_plugin_windows () +{ + for (auto window : windows) + window->show (); +} + +void focus_plugin_window (PluginHandle * plugin) +{ + int idx = find_dock_plugin (plugin); + if (idx >= 0) + windows[idx]->activateWindow (); + + aud_plugin_send_message (plugin, "grab focus", nullptr, 0); +} + +void hide_plugin_windows () +{ + for (auto window : windows) + { + window->save_size (); + window->hide (); + } +} + +void destroy_plugin_windows () +{ + for (PluginHandle * plugin : aud_plugin_list (PluginType::General)) + { + if (aud_plugin_get_enabled (plugin)) + remove_dock_plugin (plugin, nullptr); + } + + for (PluginHandle * plugin : aud_plugin_list (PluginType::Vis)) + { + if (aud_plugin_get_enabled (plugin)) + remove_dock_plugin (plugin, nullptr); + } + + hook_dissociate ("dock plugin enabled", (HookFunction) add_dock_plugin); + hook_dissociate ("dock plugin disabled", (HookFunction) remove_dock_plugin); +} diff --git a/src/skins/preset-browser.h b/src/skins-qt/plugin-window.h index 40fad45..68a2ac2 100644 --- a/src/skins/preset-browser.h +++ b/src/skins-qt/plugin-window.h @@ -1,5 +1,5 @@ /* - * preset-browser.h + * plugin-window.h * Copyright 2014 John Lindgren * * This file is part of Audacious. @@ -19,15 +19,15 @@ * using our public API to be a derived work. */ -#ifndef SKINS_PRESET_BROWSER_H -#define SKINS_PRESET_BROWSER_H +#ifndef SKINS_PLUGIN_WINDOW_H +#define SKINS_PLUGIN_WINDOW_H -void eq_preset_load_file (void); -void eq_preset_load_eqf (void); -void eq_preset_save_file (void); -void eq_preset_save_eqf (void); -void eq_preset_import_winamp (void); +class PluginHandle; -void eq_preset_browser_cleanup (void); +void create_plugin_windows (); +void show_plugin_windows (); +void focus_plugin_window (PluginHandle * plugin); +void hide_plugin_windows (); +void destroy_plugin_windows (); -#endif /* SKINS_PRESET_BROWSER_H */ +#endif /* SKINS_PLUGIN_WINDOW_H */ diff --git a/src/skins-qt/plugin.cc b/src/skins-qt/plugin.cc new file mode 100644 index 0000000..9327345 --- /dev/null +++ b/src/skins-qt/plugin.cc @@ -0,0 +1,200 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2008 Tomasz Moń + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include <stdlib.h> +#include <glib.h> +#include <QApplication> + +#define AUD_PLUGIN_QT_ONLY +#include <libaudcore/audstrings.h> +#include <libaudcore/drct.h> +#include <libaudcore/i18n.h> +#include <libaudcore/interface.h> +#include <libaudcore/runtime.h> +#include <libaudcore/plugin.h> +#include <libaudcore/hook.h> +#include <libaudqt/iface.h> +#include <libaudqt/libaudqt.h> + +#include "menus.h" +#include "plugin.h" +#include "plugin-window.h" +#include "skins_cfg.h" +#include "equalizer.h" +#include "main.h" +#include "vis-callbacks.h" +#include "playlist.h" +#include "skin.h" +#include "window.h" +#include "view.h" + +class QtSkins : public audqt::QtIfacePlugin +{ +public: + static constexpr PluginInfo info = { + N_("Winamp Classic Interface"), + PACKAGE, + nullptr, + & skins_prefs + }; + + constexpr QtSkins () : audqt::QtIfacePlugin (info) {} + + bool init (); + void cleanup (); + + void run () { audqt::run (); } + void quit () { audqt::quit (); } + + void show (bool show) + { view_show_player (show); } +}; + +EXPORT QtSkins aud_plugin_instance; + +static String user_skin_dir; +static String skin_thumb_dir; + +const char * skins_get_user_skin_dir () +{ + if (! user_skin_dir) + user_skin_dir = String (filename_build ({g_get_user_data_dir (), "audacious", "Skins"})); + + return user_skin_dir; +} + +const char * skins_get_skin_thumb_dir () +{ + if (! skin_thumb_dir) + skin_thumb_dir = String (filename_build ({g_get_user_cache_dir (), "audacious", "thumbs-unscaled"})); + + return skin_thumb_dir; +} + +static bool load_initial_skin () +{ + String path = aud_get_str ("skins", "skin"); + if (path[0] && skin_load (path)) + return true; + + StringBuf def = filename_build ({aud_get_path (AudPath::DataDir), "Skins", "Default"}); + if (skin_load (def)) + return true; + + AUDERR ("Unable to load any skin; giving up!\n"); + return false; +} + +static void skins_init_main (bool restart) +{ + int old_scale = config.scale; + + config.scale = aud_get_bool ("skins", "double_size") ? 2 : 1; + + if (restart && config.scale != old_scale) + dock_change_scale (old_scale, config.scale); + + mainwin_create (); + equalizerwin_create (); + playlistwin_create (); + + menu_init (mainwin); + + /* copy menu shortcuts to the two other windows */ + for (QAction * action : mainwin->actions ()) + { + equalizerwin->addAction (action); + playlistwin->addAction (action); + } + + view_apply_skin (); + view_apply_on_top (); + view_apply_sticky (); + + if (aud_drct_get_playing ()) + mainwin_playback_begin (); + else + mainwin_update_song_info (); + + timer_add (TimerRate::Hz4, (TimerFunc) mainwin_update_song_info); +} + +bool QtSkins::init () +{ + skins_cfg_load (); + + if (! load_initial_skin ()) + return false; + + audqt::init (); + skins_init_main (false); + + create_plugin_windows (); + + return true; +} + +static void skins_cleanup_main () +{ + mainwin_unhook (); + equalizerwin_unhook (); + playlistwin_unhook (); + + menu_cleanup (); + + timer_remove (TimerRate::Hz4, (TimerFunc) mainwin_update_song_info); + + delete mainwin; mainwin = nullptr; + delete playlistwin; playlistwin = nullptr; + delete equalizerwin; equalizerwin = nullptr; +} + +void QtSkins::cleanup () +{ + skins_cfg_save (); + + destroy_plugin_windows (); + + skins_cleanup_main (); + audqt::cleanup (); + + skin = Skin (); + + user_skin_dir = String (); + skin_thumb_dir = String (); +} + +void skins_restart () +{ + skins_cleanup_main (); + skins_init_main (true); + + if (aud_ui_is_shown ()) + view_show_player (true); +} + +void skins_close () +{ + bool handled = false; + hook_call ("window close", & handled); + + if (! handled) + aud_quit (); +} diff --git a/src/skins-qt/plugin.h b/src/skins-qt/plugin.h new file mode 100644 index 0000000..174b4aa --- /dev/null +++ b/src/skins-qt/plugin.h @@ -0,0 +1,30 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2008 Tomasz Moń + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#ifndef PLUGIN_SKINS_H +#define PLUGIN_SKINS_H + +const char * skins_get_user_skin_dir (); +const char * skins_get_skin_thumb_dir (); + +void skins_restart (); +void skins_close (); + +#endif diff --git a/src/skins-qt/skin-ini.cc b/src/skins-qt/skin-ini.cc new file mode 100644 index 0000000..6f47753 --- /dev/null +++ b/src/skins-qt/skin-ini.cc @@ -0,0 +1,278 @@ +/* + * Audacious + * Copyright 2011-2013 Audacious development team + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include <stdlib.h> +#include <glib.h> + +#include <libaudcore/inifile.h> + +#include "skins_cfg.h" +#include "skin.h" +#include "util.h" + +/* + * skin.hints parsing + */ + +typedef struct { + const char * name; + int * value_ptr; +} HintPair; + +/* in alphabetical order to allow binary search */ +static const HintPair hint_pairs[] = { + {"mainwinaboutx", & skin.hints.mainwin_about_x}, + {"mainwinabouty", & skin.hints.mainwin_about_y}, + {"mainwinbalancex", & skin.hints.mainwin_balance_x}, + {"mainwinbalancey", & skin.hints.mainwin_balance_y}, + {"mainwinclosex", & skin.hints.mainwin_close_x}, + {"mainwinclosey", & skin.hints.mainwin_close_y}, + {"mainwinejectx", & skin.hints.mainwin_eject_x}, + {"mainwinejecty", & skin.hints.mainwin_eject_y}, + {"mainwineqbuttonx", & skin.hints.mainwin_eqbutton_x}, + {"mainwineqbuttony", & skin.hints.mainwin_eqbutton_y}, + {"mainwinheight", & skin.hints.mainwin_height}, + {"mainwininfobarx", & skin.hints.mainwin_infobar_x}, + {"mainwininfobary", & skin.hints.mainwin_infobar_y}, + {"mainwinmenurowvisible", & skin.hints.mainwin_menurow_visible}, + {"mainwinminimizex", & skin.hints.mainwin_minimize_x}, + {"mainwinminimizey", & skin.hints.mainwin_minimize_y}, + {"mainwinnextx", & skin.hints.mainwin_next_x}, + {"mainwinnexty", & skin.hints.mainwin_next_y}, + {"mainwinnumber0x", & skin.hints.mainwin_number_0_x}, + {"mainwinnumber0y", & skin.hints.mainwin_number_0_y}, + {"mainwinnumber1x", & skin.hints.mainwin_number_1_x}, + {"mainwinnumber1y", & skin.hints.mainwin_number_1_y}, + {"mainwinnumber2x", & skin.hints.mainwin_number_2_x}, + {"mainwinnumber2y", & skin.hints.mainwin_number_2_y}, + {"mainwinnumber3x", & skin.hints.mainwin_number_3_x}, + {"mainwinnumber3y", & skin.hints.mainwin_number_3_y}, + {"mainwinnumber4x", & skin.hints.mainwin_number_4_x}, + {"mainwinnumber4y", & skin.hints.mainwin_number_4_y}, + {"mainwinothertextisstatus", & skin.hints.mainwin_othertext_is_status}, + {"mainwinothertextvisible", & skin.hints.mainwin_othertext_visible}, + {"mainwinpausex", & skin.hints.mainwin_pause_x}, + {"mainwinpausey", & skin.hints.mainwin_pause_y}, + {"mainwinplaystatusx", & skin.hints.mainwin_playstatus_x}, + {"mainwinplaystatusy", & skin.hints.mainwin_playstatus_y}, + {"mainwinplayx", & skin.hints.mainwin_play_x}, + {"mainwinplayy", & skin.hints.mainwin_play_y}, + {"mainwinplbuttonx", & skin.hints.mainwin_plbutton_x}, + {"mainwinplbuttony", & skin.hints.mainwin_plbutton_y}, + {"mainwinpositionx", & skin.hints.mainwin_position_x}, + {"mainwinpositiony", & skin.hints.mainwin_position_y}, + {"mainwinpreviousx", & skin.hints.mainwin_previous_x}, + {"mainwinpreviousy", & skin.hints.mainwin_previous_y}, + {"mainwinrepeatx", & skin.hints.mainwin_repeat_x}, + {"mainwinrepeaty", & skin.hints.mainwin_repeat_y}, + {"mainwinshadex", & skin.hints.mainwin_shade_x}, + {"mainwinshadey", & skin.hints.mainwin_shade_y}, + {"mainwinshufflex", & skin.hints.mainwin_shuffle_x}, + {"mainwinshuffley", & skin.hints.mainwin_shuffle_y}, + {"mainwinstopx", & skin.hints.mainwin_stop_x}, + {"mainwinstopy", & skin.hints.mainwin_stop_y}, + {"mainwinstreaminfovisible", & skin.hints.mainwin_streaminfo_visible}, + {"mainwintextvisible", & skin.hints.mainwin_text_visible}, + {"mainwintextwidth", & skin.hints.mainwin_text_width}, + {"mainwintextx", & skin.hints.mainwin_text_x}, + {"mainwintexty", & skin.hints.mainwin_text_y}, + {"mainwinvisvisible", & skin.hints.mainwin_vis_visible}, + {"mainwinvisx", & skin.hints.mainwin_vis_x}, + {"mainwinvisy", & skin.hints.mainwin_vis_y}, + {"mainwinvolumex", & skin.hints.mainwin_volume_x}, + {"mainwinvolumey", & skin.hints.mainwin_volume_y}, + {"mainwinwidth", & skin.hints.mainwin_width}, + {"textboxbitmapfontheight", & skin.hints.textbox_bitmap_font_height}, + {"textboxbitmapfontwidth", & skin.hints.textbox_bitmap_font_width}, +}; + +static int hint_pair_compare (const void * key, const void * pair) +{ + return g_ascii_strcasecmp ((const char *) key, ((const HintPair *) pair)->name); +} + +class HintsParser : public IniParser +{ +private: + bool valid_heading = false; + + void handle_heading (const char * heading) + { valid_heading = ! g_ascii_strcasecmp (heading, "skin"); } + + void handle_entry (const char * key, const char * value) + { + if (! valid_heading) + return; + + HintPair * pair = (HintPair *) bsearch (key, hint_pairs, + aud::n_elems (hint_pairs), sizeof (HintPair), hint_pair_compare); + + if (pair) + * pair->value_ptr = atoi (value); + } +}; + +void skin_load_hints (const char * path) +{ + VFSFile file = open_local_file_nocase (path, "skin.hints"); + if (file) + HintsParser ().parse (file); +} + +/* + * pledit.txt parsing + */ + +class PLColorsParser : public IniParser +{ +public: + PLColorsParser () : + valid_heading (false) {} + +private: + bool valid_heading; + + void handle_heading (const char * heading) + { valid_heading = ! g_ascii_strcasecmp (heading, "text"); } + + void handle_entry (const char * key, const char * value) + { + if (! valid_heading) + return; + + if (value[0] == '#') + value ++; + + uint32_t color = strtol (value, nullptr, 16); + + if (! g_ascii_strcasecmp (key, "normal")) + skin.colors[SKIN_PLEDIT_NORMAL] = color; + else if (! g_ascii_strcasecmp (key, "current")) + skin.colors[SKIN_PLEDIT_CURRENT] = color; + else if (! g_ascii_strcasecmp (key, "normalbg")) + skin.colors[SKIN_PLEDIT_NORMALBG] = color; + else if (! g_ascii_strcasecmp (key, "selectedbg")) + skin.colors[SKIN_PLEDIT_SELECTEDBG] = color; + } +}; + +void skin_load_pl_colors (const char * path) +{ + skin.colors[SKIN_PLEDIT_NORMAL] = 0x2499ff; + skin.colors[SKIN_PLEDIT_CURRENT] = 0xffeeff; + skin.colors[SKIN_PLEDIT_NORMALBG] = 0x0a120a; + skin.colors[SKIN_PLEDIT_SELECTEDBG] = 0x0a124a; + + VFSFile file = open_local_file_nocase (path, "pledit.txt"); + if (file) + PLColorsParser ().parse (file); +} + +/* + * region.txt parsing + */ + +class MaskParser : public IniParser +{ +public: + Index<int> numpoints[SKIN_MASK_COUNT]; + Index<int> pointlist[SKIN_MASK_COUNT]; + +private: + SkinMaskId current_id = SkinMaskId (-1); + + void handle_heading (const char * heading) + { + if (! g_ascii_strcasecmp (heading, "normal")) + current_id = SKIN_MASK_MAIN; + else if (! g_ascii_strcasecmp (heading, "windowshade")) + current_id = SKIN_MASK_MAIN_SHADE; + else if (! g_ascii_strcasecmp (heading, "equalizer")) + current_id = SKIN_MASK_EQ; + else if (! g_ascii_strcasecmp (heading, "equalizerws")) + current_id = SKIN_MASK_EQ_SHADE; + else + current_id = (SkinMaskId) -1; + } + + void handle_entry (const char * key, const char * value) + { + if (current_id == (SkinMaskId) -1) + return; + + if (! g_ascii_strcasecmp (key, "numpoints")) + numpoints[current_id] = string_to_int_array (value); + else if (! g_ascii_strcasecmp (key, "pointlist")) + pointlist[current_id] = string_to_int_array (value); + } +}; + +static Index<QRect> skin_create_mask (const Index<int> & num, + const Index<int> & point, int width, int height) +{ + Index<QRect> mask; + + int j = 0; + for (int i = 0; i < num.len (); i ++) + { + int n_points = num[i]; + if (n_points <= 0 || j + 2 * n_points > point.len ()) + break; + + int xmin = width, ymin = height, xmax = 0, ymax = 0; + + for (int k = 0; k < n_points; k ++) + { + int x = point[j + k * 2]; + int y = point[j + k * 2 + 1]; + + xmin = aud::min (xmin, x); + ymin = aud::min (ymin, y); + xmax = aud::max (xmax, x); + ymax = aud::max (ymax, y); + } + + if (xmax > xmin && ymax > ymin) + mask.append (xmin, ymin, xmax - xmin, ymax - ymin); + + j += n_points * 2; + } + + return mask; +} + +void skin_load_masks (const char * path) +{ + int sizes[SKIN_MASK_COUNT][2] = { + {skin.hints.mainwin_width, skin.hints.mainwin_height}, + {275, 16}, + {275, 116}, + {275, 16} + }; + + MaskParser parser; + VFSFile file = open_local_file_nocase (path, "region.txt"); + if (file) + parser.parse (file); + + for (int id = 0; id < SKIN_MASK_COUNT; id ++) + skin.masks[id] = skin_create_mask (parser.numpoints[id], + parser.pointlist[id], sizes[id][0], sizes[id][1]); +} diff --git a/src/skins-qt/skin.cc b/src/skins-qt/skin.cc new file mode 100644 index 0000000..3f44abd --- /dev/null +++ b/src/skins-qt/skin.cc @@ -0,0 +1,531 @@ +/* Audacious + * Copyright (C) 2005-2015 Audacious development team. + * + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> + +#include <glib.h> +#include <QPainter> + +#include <libaudcore/audstrings.h> +#include <libaudcore/runtime.h> + +#include "plugin.h" +#include "skins_cfg.h" +#include "skin.h" +#include "util.h" + +struct SkinPixmapIdMapping { + const char *name; + const char *alt_name; +}; + +static const SkinPixmapIdMapping skin_pixmap_id_map[] = { + {"main"}, + {"cbuttons"}, + {"titlebar"}, + {"shufrep"}, + {"text"}, + {"volume"}, + {"balance", "volume"}, + {"monoster"}, + {"playpaus"}, + {"nums_ex", "numbers"}, + {"posbar"}, + {"pledit"}, + {"eqmain"}, + {"eq_ex"} +}; + +static_assert (aud::n_elems (skin_pixmap_id_map) == SKIN_PIXMAP_COUNT, + "update skin_pixmap_id_map!"); + +static const uint32_t default_vis_colors[24] = { + qRgb (9, 34, 53), + qRgb (10, 18, 26), + qRgb (0, 54, 108), + qRgb (0, 58, 116), + qRgb (0, 62, 124), + qRgb (0, 66, 132), + qRgb (0, 70, 140), + qRgb (0, 74, 148), + qRgb (0, 78, 156), + qRgb (0, 82, 164), + qRgb (0, 86, 172), + qRgb (0, 92, 184), + qRgb (0, 98, 196), + qRgb (0, 104, 208), + qRgb (0, 110, 220), + qRgb (0, 116, 232), + qRgb (0, 122, 244), + qRgb (0, 128, 255), + qRgb (0, 128, 255), + qRgb (0, 104, 208), + qRgb (0, 80, 160), + qRgb (0, 56, 112), + qRgb (0, 32, 64), + qRgb (200, 200, 200) +}; + +Skin skin; + +static bool skin_load_pixmap_id (SkinPixmapId id, const char * path) +{ + StringBuf filename = skin_pixmap_locate (path, skin_pixmap_id_map[id].name, + skin_pixmap_id_map[id].alt_name); + + if (! filename) + { + AUDERR ("Skin does not contain a \"%s\" pixmap.\n", skin_pixmap_id_map[id].name); + return false; + } + + QImage & image = skin.pixmaps[id]; + image.load ((const char *) filename); + + if (! image.isNull () && image.format () != QImage::Format_RGB32) + image = image.convertToFormat (QImage::Format_RGB32); + + if (image.isNull ()) + { + AUDERR ("Error loading pixmap: %s\n", (const char *) filename); + return false; + } + + return true; +} + +static int color_diff (uint32_t a, uint32_t b) +{ + return abs (qRed (a) - qRed (b)) + abs (qGreen (a) - qGreen (b)) + abs (qBlue (a) - qBlue (b)); +} + +static void skin_get_textcolors (const QImage & image) +{ + /* + * Try to extract reasonable background and foreground colors + * from the font pixmap + */ + + /* Get a pixel from the middle of the space character */ + skin.colors[SKIN_TEXTBG] = image.pixel (152, 3); + + int max_d = -1; + for (int y = 0; y < 6; y ++) + { + for (int x = 1; x < 150; x ++) + { + uint32_t c = image.pixel (x, y); + int d = color_diff (skin.colors[SKIN_TEXTBG], c); + if (d > max_d) + { + skin.colors[SKIN_TEXTFG] = c; + max_d = d; + } + } + } +} + +static void skin_get_eq_spline_colors (const QImage & image) +{ + if (image.height () < 313) + return; + + for (int i = 0; i < 19; i ++) + skin.eq_spline_colors[i] = image.pixel (115, i + 294); +} + +static void skin_load_viscolor (const char * path) +{ + memcpy (skin.vis_colors, default_vis_colors, sizeof skin.vis_colors); + + VFSFile file = open_local_file_nocase (path, "viscolor.txt"); + if (! file) + return; + + Index<char> buffer = file.read_all (); + buffer.append (0); /* null-terminated */ + + char * string = buffer.begin (); + + for (int line = 0; string && line < 24; line ++) + { + char * next = text_parse_line (string); + Index<int> array = string_to_int_array (string); + + if (array.len () >= 3) + skin.vis_colors[line] = qRgb (array[0], array[1], array[2]); + + string = next; + } +} + +static void skin_numbers_generate_dash (QImage & image) +{ + int w = image.width (); + if (w < 99 || w >= 108) + return; + + int h = image.height (); + QImage temp (108, h, QImage::Format_RGB32); + + { + QPainter p (& temp); + p.drawImage (0, 0, image, 0, 0, 99, h); + p.drawImage (99, 0, image, 90, 0, 9, h); + p.drawImage (101, 6, image, 20, 6, 5, 1); + } + + image = std::move (temp); +} + +static bool skin_load_pixmaps (const char * path) +{ + AUDDBG ("Loading pixmaps in %s\n", path); + + /* eq_ex.bmp was added after Winamp 2.0 so some skins do not include it */ + for (int i = 0; i < SKIN_PIXMAP_COUNT; i ++) + if (! skin_load_pixmap_id ((SkinPixmapId) i, path) && i != SKIN_EQ_EX) + return false; + + skin_get_textcolors (skin.pixmaps[SKIN_TEXT]); + skin_get_eq_spline_colors (skin.pixmaps[SKIN_EQMAIN]); + skin_numbers_generate_dash (skin.pixmaps[SKIN_NUMBERS]); + + return true; +} + +static bool skin_load_data (const char * path) +{ + AUDDBG ("Attempt to load skin \"%s\"\n", path); + + if (! g_file_test (path, G_FILE_TEST_EXISTS)) + return false; + + StringBuf archive_path; + if (file_is_archive (path)) + { + AUDDBG ("Attempt to load archive\n"); + archive_path.steal (archive_decompress (path)); + + if (! archive_path) + { + AUDDBG ("Unable to extract skin archive (%s)\n", path); + return false; + } + + path = archive_path; + } + + bool success = skin_load_pixmaps (path); + + if (success) + { + skin_load_hints (path); + skin_load_pl_colors (path); + skin_load_viscolor (path); + skin_load_masks (path); + } + else + AUDDBG ("Skin loading failed\n"); + + if (archive_path) + del_directory (archive_path); + + return success; +} + +bool skin_load (const char * path) +{ + /* save current skin data */ + Skin old_skin (std::move (skin)); + + /* reset to defaults */ + skin = Skin (); + + if (skin_load_data (path)) + { + aud_set_str ("skins", "skin", path); + return true; + } + + AUDWARN ("Unable to load skin (%s).\n", (const char *) path); + + /* restore old skin data */ + skin = std::move (old_skin); + return false; +} + +void skin_install_skin (const char * path) +{ + GError * err = nullptr; + char * data; + size_t len; + + if (! g_file_get_contents (path, & data, & len, & err)) + { + AUDERR ("Failed to read %s: %s\n", path, err->message); + g_error_free (err); + return; + } + + const char * user_skin_dir = skins_get_user_skin_dir (); + make_directory (user_skin_dir); + + StringBuf base = filename_get_base (path); + StringBuf target = filename_build ({user_skin_dir, base}); + + if (g_file_set_contents (target, data, len, & err)) + aud_set_str ("skins", "skin", target); + else + { + AUDERR ("Failed to write %s: %s\n", path, err->message); + g_error_free (err); + } + + g_free (data); +} + +void skin_draw_pixbuf (QPainter & p, SkinPixmapId id, int xsrc, int ysrc, int + xdest, int ydest, int width, int height) +{ + if (! skin.pixmaps[id].isNull ()) + p.drawImage (xdest, ydest, skin.pixmaps[id], xsrc, ysrc, width, height); +} + +static void skin_draw_playlistwin_frame_top (QPainter & cr, int width, bool focus) +{ + /* The title bar skin consists of 2 sets of 4 images, 1 set + * for focused state and the other for unfocused. + * The 4 images are: + * + * a. right corner (25,20) + * b. left corner (25,20) + * c. tiler (25,20) + * d. title (100,20) + * + * min allowed width = 100+25+25 = 150 + */ + + /* get y offset of the pixmap set to use */ + int y = focus ? 0 : 21; + + /* left corner */ + skin_draw_pixbuf (cr, SKIN_PLEDIT, 0, y, 0, 0, 25, 20); + + /* titlebar title */ + skin_draw_pixbuf (cr, SKIN_PLEDIT, 26, y, (width - 100) / 2, 0, 100, 20); + + /* titlebar right corner */ + skin_draw_pixbuf (cr, SKIN_PLEDIT, 153, y, width - 25, 0, 25, 20); + + /* tile draw the remaining frame */ + + /* compute tile count */ + int c = (width - (100 + 25 + 25)) / 25; + + for (int i = 0; i < c / 2; i ++) + { + /* left of title */ + skin_draw_pixbuf (cr, SKIN_PLEDIT, 127, y, 25 + i * 25, 0, 25, 20); + + /* right of title */ + skin_draw_pixbuf (cr, SKIN_PLEDIT, 127, y, (width + 100) / 2 + i * 25, 0, 25, 20); + } + + if (c & 1) + { + /* Odd tile count, so one remaining to draw. Here we split + * it into two and draw half on either side of the title */ + skin_draw_pixbuf (cr, SKIN_PLEDIT, 127, y, ((c / 2) * 25) + 25, 0, 12, 20); + skin_draw_pixbuf (cr, SKIN_PLEDIT, 127, y, (width / 2) + ((c / 2) * 25) + 50, 0, 13, 20); + } +} + +static void skin_draw_playlistwin_frame_bottom (QPainter & cr, int width, int height) +{ + /* The bottom frame skin consists of 1 set of 4 images. + * The 4 images are: + * + * a. left corner with menu buttons (125,38) + * b. visualization window (75,38) + * c. right corner with play buttons (150,38) + * d. frame tile (25,38) + * + * (min allowed width = 125+150+25=300 + */ + + /* bottom left corner (menu buttons) */ + skin_draw_pixbuf (cr, SKIN_PLEDIT, 0, 72, 0, height - 38, 125, 38); + + int c = (width - 275) / 25; + + /* draw visualization window, if width allows */ + if (c >= 3) + { + c -= 3; + skin_draw_pixbuf (cr, SKIN_PLEDIT, 205, 0, width - (150 + 75), height - 38, 75, 38); + } + + /* Bottom right corner (playbuttons etc) */ + skin_draw_pixbuf (cr, SKIN_PLEDIT, 126, 72, width - 150, height - 38, 150, 38); + + /* Tile draw the remaining undrawn portions */ + for (int i = 0; i < c; i ++) + skin_draw_pixbuf (cr, SKIN_PLEDIT, 179, 0, 125 + i * 25, height - 38, 25, 38); +} + +static void skin_draw_playlistwin_frame_sides (QPainter & cr, int width, int height) +{ + /* The side frames consist of 2 tile images. 1 for the left, 1 for + * the right. + * a. left (12,29) + * b. right (19,29) + */ + + /* frame sides */ + for (int i = 0; i < (height - (20 + 38)) / 29; i ++) + { + /* left */ + skin_draw_pixbuf (cr, SKIN_PLEDIT, 0, 42, 0, 20 + i * 29, 12, 29); + + /* right */ + skin_draw_pixbuf (cr, SKIN_PLEDIT, 32, 42, width - 19, 20 + i * 29, 19, 29); + } +} + +void skin_draw_playlistwin_frame (QPainter & cr, int width, int height, bool focus) +{ + skin_draw_playlistwin_frame_top (cr, width, focus); + skin_draw_playlistwin_frame_bottom (cr, width, height); + skin_draw_playlistwin_frame_sides (cr, width, height); +} + +void skin_draw_playlistwin_shaded (QPainter & cr, int width, bool focus) +{ + /* The shade mode titlebar skin consists of 4 images: + * a) left corner offset (72,42) size (25,14) + * b) right corner, focused offset (99,57) size (50,14) + * c) right corner, unfocused offset (99,42) size (50,14) + * d) bar tile offset (72,57) size (25,14) + */ + + /* left corner */ + skin_draw_pixbuf (cr, SKIN_PLEDIT, 72, 42, 0, 0, 25, 14); + + /* bar tile */ + for (int i = 0; i < (width - 75) / 25; i ++) + skin_draw_pixbuf (cr, SKIN_PLEDIT, 72, 57, (i * 25) + 25, 0, 25, 14); + + /* right corner */ + skin_draw_pixbuf (cr, SKIN_PLEDIT, 99, focus ? 42 : 57, width - 50, 0, 50, 14); +} + +void skin_draw_mainwin_titlebar (QPainter & cr, bool shaded, bool focus) +{ + /* The titlebar skin consists of 2 sets of 2 images, one for for + * shaded and the other for unshaded mode, giving a total of 4. + * The images are exactly 275x14 pixels, aligned and arranged + * vertically on each other in the pixmap in the following order: + * + * a) unshaded, focused offset (27, 0) + * b) unshaded, unfocused offset (27, 15) + * c) shaded, focused offset (27, 29) + * d) shaded, unfocused offset (27, 42) + */ + + int y_offset = shaded ? (focus ? 29 : 42) : (focus ? 0 : 15); + + skin_draw_pixbuf (cr, SKIN_TITLEBAR, 27, y_offset, 0, 0, + skin.hints.mainwin_width, 14); +} + +/* parse a subset of Pango font descriptions */ +QFont * qfont_from_string (const char * name) +{ + auto family = str_copy (name); + int size = 0; + QFont::Weight weight = QFont::Normal; + QFont::Style style = QFont::StyleNormal; + QFont::Stretch stretch = QFont::Unstretched; + + while (1) + { + /* check for attributes */ + bool attr_found = false; + const char * space = strrchr (family, ' '); + + if (space) + { + const char * attr = space + 1; + int num = str_to_int (attr); + + attr_found = true; + + if (num > 0) + size = num; + else if (! strcmp (attr, "Light")) + weight = QFont::Light; + else if (! strcmp (attr, "Bold")) + weight = QFont::Bold; + else if (! strcmp (attr, "Oblique")) + style = QFont::StyleOblique; + else if (! strcmp (attr, "Italic")) + style = QFont::StyleItalic; + else if (! strcmp (attr, "Condensed")) + stretch = QFont::Condensed; + else if (! strcmp (attr, "Expanded")) + stretch = QFont::Expanded; + else + attr_found = false; + } + + if (! attr_found) + { + auto font = new QFont ((const char *) family); + + /* check for a recognized font family */ + if (! space || font->exactMatch ()) + { + if (size > 0) + font->setPointSize (size); + if (weight != QFont::Normal) + font->setWeight (weight); + if (style != QFont::StyleNormal) + font->setStyle (style); + if (stretch != QFont::Unstretched) + font->setStretch (stretch); + + return font; + } + + delete font; + } + + family.resize (space - family); + } +} diff --git a/src/skins-qt/skin.h b/src/skins-qt/skin.h new file mode 100644 index 0000000..b411982 --- /dev/null +++ b/src/skins-qt/skin.h @@ -0,0 +1,198 @@ +/* Audacious + * Copyright (C) 2005-2011 Audacious development team. + * + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#ifndef SKIN_H +#define SKIN_H + +#include <stdint.h> +#include <QImage> + +#include <libaudcore/index.h> +#include <libaudcore/objects.h> + +typedef enum { + SKIN_MAIN = 0, + SKIN_CBUTTONS, + SKIN_TITLEBAR, + SKIN_SHUFREP, + SKIN_TEXT, + SKIN_VOLUME, + SKIN_BALANCE, + SKIN_MONOSTEREO, + SKIN_PLAYPAUSE, + SKIN_NUMBERS, + SKIN_POSBAR, + SKIN_PLEDIT, + SKIN_EQMAIN, + SKIN_EQ_EX, + SKIN_PIXMAP_COUNT +} SkinPixmapId; + +typedef enum { + SKIN_MASK_MAIN = 0, + SKIN_MASK_MAIN_SHADE, + SKIN_MASK_EQ, + SKIN_MASK_EQ_SHADE, + SKIN_MASK_COUNT +} SkinMaskId; + +typedef enum { + SKIN_PLEDIT_NORMAL = 0, + SKIN_PLEDIT_CURRENT, + SKIN_PLEDIT_NORMALBG, + SKIN_PLEDIT_SELECTEDBG, + SKIN_TEXTBG, + SKIN_TEXTFG, + SKIN_COLOR_COUNT +} SkinColorId; + +struct SkinHints { + /* Vis properties */ + int mainwin_vis_x = 24; + int mainwin_vis_y = 43; + int mainwin_vis_visible = true; + + /* Text properties */ + int mainwin_text_x = 112; + int mainwin_text_y = 27; + int mainwin_text_width = 153; + int mainwin_text_visible = true; + + /* Infobar properties */ + int mainwin_infobar_x = 112; + int mainwin_infobar_y = 43; + int mainwin_othertext_visible = false; + + int mainwin_number_0_x = 36; + int mainwin_number_0_y = 26; + + int mainwin_number_1_x = 48; + int mainwin_number_1_y = 26; + + int mainwin_number_2_x = 60; + int mainwin_number_2_y = 26; + + int mainwin_number_3_x = 78; + int mainwin_number_3_y = 26; + + int mainwin_number_4_x = 90; + int mainwin_number_4_y = 26; + + int mainwin_playstatus_x = 24; + int mainwin_playstatus_y = 28; + + int mainwin_volume_x = 107; + int mainwin_volume_y = 57; + + int mainwin_balance_x = 177; + int mainwin_balance_y = 57; + + int mainwin_position_x = 16; + int mainwin_position_y = 72; + + int mainwin_previous_x = 16; + int mainwin_previous_y = 88; + + int mainwin_play_x = 39; + int mainwin_play_y = 88; + + int mainwin_pause_x = 62; + int mainwin_pause_y = 88; + + int mainwin_stop_x = 85; + int mainwin_stop_y = 88; + + int mainwin_next_x = 108; + int mainwin_next_y = 88; + + int mainwin_eject_x = 136; + int mainwin_eject_y = 89; + + int mainwin_eqbutton_x = 219; + int mainwin_eqbutton_y = 58; + + int mainwin_plbutton_x = 242; + int mainwin_plbutton_y = 58; + + int mainwin_shuffle_x = 164; + int mainwin_shuffle_y = 89; + + int mainwin_repeat_x = 210; + int mainwin_repeat_y = 89; + + int mainwin_about_x = 247; + int mainwin_about_y = 83; + + int mainwin_minimize_x = 244; + int mainwin_minimize_y = 3; + + int mainwin_shade_x = 254; + int mainwin_shade_y = 3; + + int mainwin_close_x = 264; + int mainwin_close_y = 3; + + int mainwin_width = 275; + int mainwin_height = 116; + + int mainwin_menurow_visible = true; + int mainwin_streaminfo_visible = true; + int mainwin_othertext_is_status = false; + + int textbox_bitmap_font_width = 5; + int textbox_bitmap_font_height = 6; +}; + +struct Skin { + SkinHints hints; + uint32_t colors[SKIN_COLOR_COUNT] {}; + uint32_t eq_spline_colors[19] {}; + uint32_t vis_colors[24] {}; + + QImage pixmaps[SKIN_PIXMAP_COUNT]; + Index<QRect> masks[SKIN_MASK_COUNT]; +}; + +extern Skin skin; + +bool skin_load (const char * path); + +void skin_draw_pixbuf (QPainter & p, SkinPixmapId id, int xsrc, int ysrc, + int xdest, int ydest, int width, int height); + +void skin_install_skin (const char * path); + +void skin_draw_playlistwin_shaded (QPainter & cr, int width, bool focus); +void skin_draw_playlistwin_frame (QPainter & cr, int width, int height, bool focus); +void skin_draw_mainwin_titlebar (QPainter & cr, bool shaded, bool focus); + +QFont * qfont_from_string (const char * name); + +/* ui_skin_load_ini.c */ +void skin_load_hints (const char * path); +void skin_load_pl_colors (const char * path); +void skin_load_masks (const char * path); + +#endif diff --git a/src/skins-qt/skins_cfg.cc b/src/skins-qt/skins_cfg.cc new file mode 100644 index 0000000..14ea4b5 --- /dev/null +++ b/src/skins-qt/skins_cfg.cc @@ -0,0 +1,348 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2008 Tomasz Moń + * Copyright (c) 2011 John Lindgren + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include <string.h> + +#include <libaudcore/i18n.h> +#include <libaudcore/runtime.h> +#include <libaudcore/preferences.h> +#include <libaudcore/audstrings.h> + +#include "dnd.h" +#include "skins_cfg.h" +#include "main.h" +#include "vis-callbacks.h" +#include "playlist.h" +#include "skin.h" +#include "playlist-widget.h" +#include "textbox.h" +#include "skinselector.h" +#include "vis.h" +#include "util.h" +#include "view.h" + +static const char * const skins_defaults[] = { + /* general */ + "autoscroll_songname", "TRUE", + "mainwin_font", "Sans Bold 9", + "mainwin_use_bitmapfont", "TRUE", + "playlist_font", "Sans Bold 8", + "record", "FALSE", + "show_remaining_time", "FALSE", + "twoway_scroll", "FALSE", + + /* visualizer */ + "analyzer_falloff", aud::numeric_string<FALLOFF_FAST>::str, + "analyzer_mode", aud::numeric_string<ANALYZER_NORMAL>::str, + "analyzer_peaks", "TRUE", + "analyzer_type", aud::numeric_string<ANALYZER_BARS>::str, + "peaks_falloff", aud::numeric_string<FALLOFF_SLOW>::str, + "scope_mode", aud::numeric_string<SCOPE_DOT>::str, + "vis_type", aud::numeric_string<VIS_ANALYZER>::str, + "voiceprint_mode", aud::numeric_string<VOICEPRINT_NORMAL>::str, + "vu_mode", aud::numeric_string<VU_SMOOTH>::str, + + /* windows */ + "always_on_top", "FALSE", + "double_size", "FALSE", + "equalizer_shaded", "FALSE", + "equalizer_visible", "FALSE", + "equalizer_x", "20", + "equalizer_y", "136", + "player_shaded", "FALSE", + "player_x", "20", + "player_y", "20", + "playlist_shaded", "FALSE", + "playlist_visible", "FALSE", + "playlist_x", "295", + "playlist_y", "20", + "playlist_width", "275", + "playlist_height", "232", + "sticky", "FALSE", + + nullptr +}; + +skins_cfg_t config; + +static const struct skins_cfg_boolent_t { + const char * name; + bool * ptr; +} skins_boolents[] = +{ + /* general */ + {"autoscroll_songname", & config.autoscroll}, + {"mainwin_use_bitmapfont", & config.mainwin_use_bitmapfont}, + {"twoway_scroll", & config.twoway_scroll}, + + /* visualizer */ + {"analyzer_peaks", & config.analyzer_peaks} +}; + +static const struct { + const char * name; + int * ptr; +} skins_numents[] = +{ + /* visualizer */ + {"analyzer_falloff", & config.analyzer_falloff}, + {"analyzer_mode", & config.analyzer_mode}, + {"analyzer_type", & config.analyzer_type}, + {"peaks_falloff", & config.peaks_falloff}, + {"scope_mode", & config.scope_mode}, + {"vis_type", & config.vis_type}, + {"voiceprint_mode", & config.voiceprint_mode}, + {"vu_mode", & config.vu_mode}, + + /* windows */ + {"equalizer_x", & config.equalizer_x}, + {"equalizer_y", & config.equalizer_y}, + {"player_x", & config.player_x}, + {"player_y", & config.player_y}, + {"playlist_x", & config.playlist_x}, + {"playlist_y", & config.playlist_y}, + {"playlist_width", & config.playlist_width}, + {"playlist_height", & config.playlist_height} +}; + +static String selected_skin; +static Index<ComboItem> skin_combo; + +void skins_cfg_load () +{ + aud_config_set_defaults ("skins", skins_defaults); + + for (auto & boolent : skins_boolents) + * boolent.ptr = aud_get_bool ("skins", boolent.name); + + for (auto & nument : skins_numents) + * nument.ptr = aud_get_int ("skins", nument.name); +} + +void skins_cfg_save () +{ + for (auto & boolent : skins_boolents) + aud_set_bool ("skins", boolent.name, * boolent.ptr); + + for (auto & nument : skins_numents) + aud_set_int ("skins", nument.name, * nument.ptr); +} + +static ArrayRef<ComboItem> skin_combo_fill () +{ + selected_skin = aud_get_str ("skins", "skin"); + + skin_combo.clear (); + skinlist_update (); + + for (auto & node : skinlist) + skin_combo.append (node.name, node.path); + + return {skin_combo.begin (), skin_combo.len ()}; +} + +static void skin_select_cb () +{ + if (skin_load (selected_skin)) + view_apply_skin (); +} + +static void mainwin_font_set_cb () +{ + if (! config.mainwin_use_bitmapfont) + mainwin_info->set_font (aud_get_str ("skins", "mainwin_font")); + else + mainwin_info->set_font (nullptr); +} + +static void playlist_font_set_cb () +{ + playlistwin_list->set_font (aud_get_str ("skins", "playlist_font")); +} + +static void autoscroll_set_cb () +{ + if (! aud_get_bool ("skins", "mainwin_shaded")) + mainwin_info->set_scroll (config.autoscroll); + if (aud_get_bool ("skins", "playlist_shaded")) + playlistwin_sinfo->set_scroll (config.autoscroll); +} + +static void vis_reset_cb () +{ + mainwin_vis->clear (); + mainwin_svis->clear (); + start_stop_visual (false); +} + +static const PreferencesWidget font_table_elements[] = { + WidgetFonts (N_("Player:"), + WidgetString ("skins", "mainwin_font", mainwin_font_set_cb), + {N_("Select main player window font:")}), + WidgetFonts (N_("Playlist:"), + WidgetString ("skins", "playlist_font", playlist_font_set_cb), + {N_("Select playlist font:")}) +}; + +static const PreferencesWidget skins_widgets_general[] = { + WidgetLabel (N_("<b>Skin</b>")), + WidgetCombo (nullptr, + WidgetString (selected_skin, skin_select_cb), + {nullptr, skin_combo_fill}), + WidgetLabel (N_("<b>Fonts</b>")), + WidgetTable ({{font_table_elements}}), + WidgetCheck (N_("Use bitmap fonts (supports ASCII only)"), + WidgetBool (config.mainwin_use_bitmapfont, mainwin_font_set_cb)), + WidgetCheck (N_("Scroll song title"), + WidgetBool (config.autoscroll, autoscroll_set_cb)), + WidgetCheck (N_("Scroll song title in both directions"), + WidgetBool (config.twoway_scroll, autoscroll_set_cb)) +}; + +static ComboItem vis_mode_elements[] = { + ComboItem (N_("Analyzer"), VIS_ANALYZER), + ComboItem (N_("Scope"), VIS_SCOPE), + ComboItem (N_("Voiceprint / VU meter"), VIS_VOICEPRINT), + ComboItem (N_("Off"), VIS_OFF) +}; + +static ComboItem analyzer_mode_elements[] = { + ComboItem (N_("Normal"), ANALYZER_NORMAL), + ComboItem (N_("Fire"), ANALYZER_FIRE), + ComboItem (N_("Vertical lines"), ANALYZER_VLINES) +}; + +static ComboItem analyzer_type_elements[] = { + ComboItem (N_("Lines"), ANALYZER_LINES), + ComboItem (N_("Bars"), ANALYZER_BARS) +}; + +static ComboItem falloff_elements[] = { + ComboItem (N_("Slowest"), FALLOFF_SLOWEST), + ComboItem (N_("Slow"), FALLOFF_SLOW), + ComboItem (N_("Medium"), FALLOFF_MEDIUM), + ComboItem (N_("Fast"), FALLOFF_FAST), + ComboItem (N_("Fastest"), FALLOFF_FASTEST) +}; + +static ComboItem scope_mode_elements[] = { + ComboItem (N_("Dots"), SCOPE_DOT), + ComboItem (N_("Line"), SCOPE_LINE), + ComboItem (N_("Solid"), SCOPE_SOLID) +}; + +static ComboItem voiceprint_mode_elements[] = { + ComboItem (N_("Normal"), VOICEPRINT_NORMAL), + ComboItem (N_("Fire"), VOICEPRINT_FIRE), + ComboItem (N_("Ice"), VOICEPRINT_ICE) +}; + +static ComboItem vu_mode_elements[] = { + ComboItem (N_("Normal"), VU_NORMAL), + ComboItem (N_("Smooth"), VU_SMOOTH) +}; + +static const PreferencesWidget analyzer_table[] = { + WidgetCombo (N_("Coloring:"), + WidgetInt (config.analyzer_mode, vis_reset_cb), + {{analyzer_mode_elements}}), + WidgetCombo (N_("Style:"), + WidgetInt (config.analyzer_type, vis_reset_cb), + {{analyzer_type_elements}}), + WidgetCombo (N_("Falloff:"), + WidgetInt (config.analyzer_falloff, vis_reset_cb), + {{falloff_elements}}), + WidgetCombo (N_("Peak falloff:"), + WidgetInt (config.peaks_falloff, vis_reset_cb), + {{falloff_elements}}) +}; + +static const PreferencesWidget misc_table[] = { + WidgetCombo (N_("Scope Style:"), + WidgetInt (config.scope_mode, vis_reset_cb), + {{scope_mode_elements}}), + WidgetCombo (N_("Voiceprint Coloring:"), + WidgetInt (config.voiceprint_mode, vis_reset_cb), + {{voiceprint_mode_elements}}), + WidgetCombo (N_("VU Meter Style:"), + WidgetInt (config.vu_mode, vis_reset_cb), + {{vu_mode_elements}}) +}; + +static const PreferencesWidget skins_widgets_vis[] = { + WidgetLabel (N_("<b>Type</b>")), + WidgetCombo (N_("Visualization type:"), + WidgetInt (config.vis_type, vis_reset_cb), + {{vis_mode_elements}}), + WidgetLabel (N_("<b>Analyzer</b>")), + WidgetCheck (N_("Show peaks"), + WidgetBool (config.analyzer_peaks, vis_reset_cb)), + WidgetTable ({{analyzer_table}}), + WidgetLabel (N_("<b>Miscellaneous</b>")), + WidgetTable ({{misc_table}}) +}; + +static const NotebookTab skins_notebook_tabs[] = { + {N_("General"), {skins_widgets_general}}, + {N_("Visualization"), {skins_widgets_vis}} +}; + +static const PreferencesWidget skins_widgets[] = { + WidgetNotebook ({{skins_notebook_tabs}}) +}; + +const PluginPreferences skins_prefs = {{skins_widgets}}; + +#if 0 +void on_skin_view_drag_data_received (GtkWidget * widget, GdkDragContext * context, + int x, int y, GtkSelectionData * selection_data, unsigned info, unsigned time, void *) +{ + const char * data = (const char *) gtk_selection_data_get_data (selection_data); + g_return_if_fail (data); + + const char * end = strchr (data, '\r'); + if (! end) + end = strchr (data, '\n'); + if (! end) + end = data + strlen (data); + + StringBuf path = str_copy (data, end - data); + + if (strstr (path, "://")) + { + StringBuf path2 = uri_to_filename (path); + if (path2) + path.steal (std::move (path2)); + } + + if (file_is_archive (path)) + { + if (! skin_load (path)) + return; + + view_apply_skin (); + skin_install_skin(path); + + if (skin_view) + skin_view_update ((GtkTreeView *) skin_view); + } +} +#endif diff --git a/src/skins-qt/skins_cfg.h b/src/skins-qt/skins_cfg.h new file mode 100644 index 0000000..9853150 --- /dev/null +++ b/src/skins-qt/skins_cfg.h @@ -0,0 +1,57 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2008 Tomasz Moń + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#ifndef SKINS_CFG_H +#define SKINS_CFG_H + +struct PluginPreferences; + +typedef struct { + int player_x, player_y; + int equalizer_x, equalizer_y; + int playlist_x, playlist_y; + int playlist_width, playlist_height; + int scale; + bool autoscroll; + bool analyzer_peaks; + bool twoway_scroll; + int vis_type; + int analyzer_mode, analyzer_type; + int scope_mode; + int voiceprint_mode; + int vu_mode; + int analyzer_falloff, peaks_falloff; + bool mainwin_use_bitmapfont; +} skins_cfg_t; + +extern skins_cfg_t config; + +void skins_cfg_load (); +void skins_cfg_save (); + +#if 0 +void on_skin_view_drag_data_received (GtkWidget * widget, + GdkDragContext * context, int x, int y, GtkSelectionData * selection_data, + unsigned info, unsigned time, void * data); +#endif + +extern const PluginPreferences skins_prefs; + +#endif diff --git a/src/skins-qt/skinselector.cc b/src/skins-qt/skinselector.cc new file mode 100644 index 0000000..f8de313 --- /dev/null +++ b/src/skins-qt/skinselector.cc @@ -0,0 +1,129 @@ +/* + * ui_skinselector.c + * Copyright 1998-2003 XMMS Development Team + * Copyright 2003-2004 BMP Development Team + * Copyright 2011 John Lindgren + * + * This file is part of Audacious. + * + * Audacious 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, version 2 or version 3 of the License. + * + * Audacious 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 + * Audacious. If not, see <http://www.gnu.org/licenses/>. + * + * The Audacious team does not consider modular code linking to Audacious or + * using our public API to be a derived work. + */ + +#include <stdlib.h> +#include <glib.h> + +#include <libaudcore/audstrings.h> +#include <libaudcore/i18n.h> +#include <libaudcore/runtime.h> + +#include "plugin.h" +#include "skin.h" +#include "skinselector.h" +#include "util.h" + +Index<SkinNode> skinlist; + +#if 0 +static GdkPixbuf * skin_get_preview (const char * path) +{ + GdkPixbuf * preview = nullptr; + + StringBuf archive_path; + if (file_is_archive (path)) + { + archive_path.steal (archive_decompress (path)); + if (! archive_path) + return nullptr; + + path = archive_path; + } + + StringBuf preview_path = skin_pixmap_locate (path, "main"); + if (preview_path) + preview = gdk_pixbuf_new_from_file (preview_path, nullptr); + + if (archive_path) + del_directory (archive_path); + + return preview; +} + +static GdkPixbuf * skin_get_thumbnail (const char * path) +{ + StringBuf base = filename_get_base (path); + base.insert (-1, ".png"); + + StringBuf thumbname = filename_build ({skins_get_skin_thumb_dir (), base}); + GdkPixbuf * thumb = nullptr; + + if (g_file_test (thumbname, G_FILE_TEST_EXISTS)) + thumb = gdk_pixbuf_new_from_file (thumbname, nullptr); + + if (! thumb) + { + thumb = skin_get_preview (path); + + if (thumb) + { + make_directory (skins_get_skin_thumb_dir ()); + gdk_pixbuf_save (thumb, thumbname, "png", nullptr, nullptr); + } + } + + if (thumb) + audgui_pixbuf_scale_within (& thumb, audgui_get_dpi () * 3 / 2); + + return thumb; +} +#endif + +static void scan_skindir_func (const char * path, const char * basename) +{ + if (g_file_test (path, G_FILE_TEST_IS_REGULAR)) + { + if (file_is_archive (path)) + skinlist.append (String (archive_basename (basename)), + String (_("Archived Winamp 2.x skin")), String (path)); + } + else if (g_file_test (path, G_FILE_TEST_IS_DIR)) + skinlist.append (String (basename), + String (_("Unarchived Winamp 2.x skin")), String (path)); +} + +static int skinlist_compare_func (const SkinNode & a, const SkinNode & b, void *) +{ + return str_compare (a.name, b.name); +} + +void skinlist_update () +{ + skinlist.clear (); + + const char * user_skin_dir = skins_get_user_skin_dir (); + if (g_file_test (user_skin_dir, G_FILE_TEST_EXISTS)) + dir_foreach (user_skin_dir, scan_skindir_func); + + StringBuf path = filename_build ({aud_get_path (AudPath::DataDir), "Skins"}); + dir_foreach (path, scan_skindir_func); + + const char * skinsdir = getenv ("SKINSDIR"); + if (skinsdir) + { + for (const String & dir : str_list_to_index (skinsdir, ":")) + dir_foreach (dir, scan_skindir_func); + } + + skinlist.sort (skinlist_compare_func, nullptr); +} diff --git a/src/skins-qt/skinselector.h b/src/skins-qt/skinselector.h new file mode 100644 index 0000000..4d1e8cc --- /dev/null +++ b/src/skins-qt/skinselector.h @@ -0,0 +1,37 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#ifndef SKINS_UI_SKINSELECTOR_H +#define SKINS_UI_SKINSELECTOR_H + +#include <libaudcore/index.h> +#include <libaudcore/objects.h> + +struct SkinNode { + String name, desc, path; +}; + +extern Index<SkinNode> skinlist; + +void skinlist_update (); + +#endif /* SKINS_UI_SKINSELECTOR_H */ diff --git a/src/skins-qt/svis.cc b/src/skins-qt/svis.cc new file mode 100644 index 0000000..82e3d81 --- /dev/null +++ b/src/skins-qt/svis.cc @@ -0,0 +1,208 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007-2011 Audacious development team. + * + * Based on: + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include <string.h> +#include <libaudcore/objects.h> + +#include "skins_cfg.h" +#include "skin.h" +#include "vis.h" + +static const int svis_analyzer_colors[] = {14, 11, 8, 5, 2}; +static const int svis_scope_colors[] = {20, 19, 18, 19, 20}; +static const int svis_vu_normal_colors[] = {16, 14, 12, 10, 8, 6, 4, 2}; + +#define RGB_SEEK(x,y) (set = rgb + 38 * (y) + (x)) +#define RGB_SET(c) (* set ++ = (c)) +#define RGB_SET_Y(c) do {* set = (c); set += 38;} while (0) +#define RGB_SET_INDEX(c) RGB_SET (skin.vis_colors[c]) +#define RGB_SET_INDEX_Y(c) RGB_SET_Y (skin.vis_colors[c]) + +void SmallVis::draw (QPainter & cr) +{ + uint32_t rgb[38 * 5]; + uint32_t * set; + + RGB_SEEK (0, 0); + for (int x = 0; x < 38 * 5; x ++) + RGB_SET_INDEX (0); + + switch (config.vis_type) + { + case VIS_ANALYZER: + { + bool bars = (config.analyzer_type == ANALYZER_BARS); + + for (int x = 0; x < 38; x ++) + { + if (bars && (x % 3) == 2) + continue; + + int h = m_data[bars ? (x / 3) : x]; + h = aud::clamp (h, 0, 5); + RGB_SEEK (x, 5 - h); + + for (int y = 0; y < h; y ++) + RGB_SET_INDEX_Y (svis_analyzer_colors[h - 1 - y]); + } + + break; + } + case VIS_VOICEPRINT: + switch (config.vu_mode) + { + case VU_NORMAL: + for (int y = 0; y < 5; y ++) + { + if (y == 2) + continue; + + int h = (m_data[y / 3] * 8 + 19) / 38; + h = aud::clamp (h, 0, 8); + RGB_SEEK (0, y); + + for (int x = 0; x < h; x ++) + { + RGB_SET_INDEX (svis_vu_normal_colors[x]); + RGB_SET_INDEX (svis_vu_normal_colors[x]); + RGB_SET_INDEX (svis_vu_normal_colors[x]); + set += 2; + } + } + break; + default: /* VU_SMOOTH */ + for (int y = 0; y < 5; y ++) + { + if (y == 2) + continue; + + int h = m_data[y / 3]; + h = aud::clamp (h, 0, 38); + RGB_SEEK (0, y); + + for (int x = 0; x < h; x ++) + RGB_SET_INDEX (17 - (x * 16) / 38); + } + break; + } + break; + case VIS_SCOPE: + { + static const int scale[17] = {0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 3, 4, + 4, 4, 4, 4, 4}; + + if (! m_active) + goto DRAW; + + switch (config.scope_mode) + { + case SCOPE_DOT: + for (int x = 0; x < 38; x ++) + { + int h = scale[aud::clamp (m_data[2 * x], 0, 16)]; + RGB_SEEK (x, h); + RGB_SET_INDEX (svis_scope_colors[h]); + } + break; + case SCOPE_LINE: + { + for (int x = 0; x < 37; x ++) + { + int h = scale[aud::clamp (m_data[2 * x], 0, 16)]; + int h2 = scale[aud::clamp (m_data[2 * (x + 1)], 0, 16)]; + + if (h < h2) h2 --; + else if (h > h2) {int temp = h; h = h2 + 1; h2 = temp;} + + RGB_SEEK (x, h); + for (int y = h; y <= h2; y ++) + RGB_SET_INDEX_Y (svis_scope_colors[y]); + } + + int h = scale[aud::clamp (m_data[74], 0, 16)]; + RGB_SEEK (37, h); + RGB_SET_INDEX (svis_scope_colors[h]); + break; + } + default: /* SCOPE_SOLID */ + for (int x = 0; x < 38; x ++) + { + int h = scale[aud::clamp (m_data[2 * x], 0, 16)]; + int h2; + + if (h < 2) + h2 = 2; + else + { + h2 = h; + h = 2; + } + + RGB_SEEK (x, h); + for (int y = h; y <= h2; y ++) + RGB_SET_INDEX_Y (svis_scope_colors[y]); + } + break; + } + break; + } + } + +DRAW: + QImage image ((unsigned char *) rgb, 38, 5, 4 * 38, QImage::Format_RGB32); + cr.drawImage (0, 0, image); +} + +SmallVis::SmallVis () +{ + set_scale (config.scale); + add_drawable (38, 5); + clear (); +} + +void SmallVis::clear () +{ + m_active = false; + memset (m_data, 0, sizeof m_data); + queue_draw (); +} + +void SmallVis::render (const unsigned char * data) +{ + if (config.vis_type == VIS_VOICEPRINT) + { + for (int i = 0; i < 2; i ++) + m_data[i] = data[i]; + } + else + { + for (int i = 0; i < 75; i ++) + m_data[i] = data[i]; + } + + m_active = true; + draw_now (); +} diff --git a/src/skins-qt/textbox.cc b/src/skins-qt/textbox.cc new file mode 100644 index 0000000..5e5483a --- /dev/null +++ b/src/skins-qt/textbox.cc @@ -0,0 +1,294 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2011 John Lindgren + * + * Based on: + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include <string.h> + +#include <libaudcore/audstrings.h> +#include <libaudcore/hook.h> +#include <libaudcore/objects.h> + +#include "skins_cfg.h" +#include "skin.h" +#include "textbox.h" + +#define DELAY 50 + +static Index<TextBox *> textboxes; + +void TextBox::draw (QPainter & cr) +{ + if (m_scrolling) + { + cr.drawImage (-m_offset * config.scale, 0, * m_buf); + if (-m_offset + m_buf_width < m_width) + cr.drawImage ((-m_offset + m_buf_width) * config.scale, 0, * m_buf); + } + else + cr.drawImage (0, 0, * m_buf); +} + +bool TextBox::button_press (QMouseEvent * event) +{ + return press ? press (event) : false; +} + +void TextBox::scroll_timeout () +{ + if (m_delay < DELAY) + { + m_delay ++; + return; + } + + if (m_two_way && m_backward) + m_offset --; + else + m_offset ++; + + if (m_two_way && (m_backward ? (m_offset <= 0) : (m_offset + m_width >= m_buf_width))) + { + m_backward = ! m_backward; + m_delay = 0; + } + + if (! m_two_way && m_offset >= m_buf_width) + m_offset = 0; + + draw_now (); +} + +void TextBox::render_vector (const char * text) +{ + QRect ink = m_metrics->tightBoundingRect (text); + int logical_width = m_metrics->width (text); + + /* use logical width so as not to trim off the trailing space of the " --- " */ + /* use ink height since vertical space is quite limited */ + int width = aud::max (-ink.x () + logical_width, 1); + int height = aud::max (ink.height (), 1); + + resize (m_width * config.scale, height); + + m_buf_width = aud::max ((width + config.scale - 1) / config.scale, m_width); + m_buf.capture (new QImage (m_buf_width * config.scale, height, QImage::Format_RGB32)); + + QPainter cr (m_buf.get ()); + + cr.fillRect (cr.window (), QColor (skin.colors[SKIN_TEXTBG])); + + cr.setFont (* m_font); + cr.setPen (QColor (skin.colors[SKIN_TEXTFG])); + cr.drawText (-ink.x (), -ink.y (), text); +} + +static void lookup_char (const char c, int * x, int * y) +{ + int tx, ty; + + switch (c) + { + case '"': tx = 26; ty = 0; break; + case '@': tx = 27; ty = 0; break; + case ' ': tx = 29; ty = 0; break; + case ':': + case ';': + case '|': tx = 12; ty = 1; break; + case '(': + case '{': tx = 13; ty = 1; break; + case ')': + case '}': tx = 14; ty = 1; break; + case '-': + case '~': tx = 15; ty = 1; break; + case '`': + case '\'': tx = 16; ty = 1; break; + case '!': tx = 17; ty = 1; break; + case '_': tx = 18; ty = 1; break; + case '+': tx = 19; ty = 1; break; + case '\\': tx = 20; ty = 1; break; + case '/': tx = 21; ty = 1; break; + case '[': tx = 22; ty = 1; break; + case ']': tx = 23; ty = 1; break; + case '^': tx = 24; ty = 1; break; + case '&': tx = 25; ty = 1; break; + case '%': tx = 26; ty = 1; break; + case '.': + case ',': tx = 27; ty = 1; break; + case '=': tx = 28; ty = 1; break; + case '$': tx = 29; ty = 1; break; + case '#': tx = 30; ty = 1; break; + case '?': tx = 3; ty = 2; break; + case '*': tx = 4; ty = 2; break; + default: tx = 3; ty = 2; break; /* '?' */ + } + + * x = tx * skin.hints.textbox_bitmap_font_width; + * y = ty * skin.hints.textbox_bitmap_font_height; +} + +void TextBox::render_bitmap (const char * text) +{ + int cw = skin.hints.textbox_bitmap_font_width; + int ch = skin.hints.textbox_bitmap_font_height; + + resize (m_width * config.scale, ch * config.scale); + + auto ucs4 = QString (text).toUcs4 (); + + m_buf_width = aud::max (cw * ucs4.length (), m_width); + m_buf.capture (new QImage (m_buf_width * config.scale, ch * config.scale, + QImage::Format_RGB32)); + + QPainter cr (m_buf.get ()); + if (config.scale != 1) + cr.setTransform (QTransform ().scale (config.scale, config.scale)); + + for (int x = 0, i = 0; x < m_buf_width; x += cw, i ++) + { + unsigned c = (i < ucs4.length ()) ? ucs4[i] : ' '; + int cx = 0, cy = 0; + + if (c >= 'A' && c <= 'Z') + cx = cw * (c - 'A'); + else if (c >= 'a' && c <= 'z') + cx = cw * (c - 'a'); + else if (c >= '0' && c <= '9') + { + cx = cw * (c - '0'); + cy = ch; + } + else + lookup_char (c, & cx, & cy); + + skin_draw_pixbuf (cr, SKIN_TEXT, cx, cy, x, 0, cw, ch); + } +} + +void TextBox::render () +{ + m_scrolling = false; + m_backward = false; + m_offset = 0; + m_delay = 0; + + const char * text = m_text ? m_text : ""; + + if (m_font) + render_vector (text); + else + render_bitmap (text); + + if (m_may_scroll && m_buf_width > m_width) + { + m_scrolling = true; + + if (! m_two_way) + { + StringBuf temp = str_printf ("%s --- ", text); + + if (m_font) + render_vector (temp); + else + render_bitmap (temp); + } + } + + queue_draw (); + + if (m_scrolling) + scroll_timer.start (); + else + scroll_timer.stop (); +} + +void TextBox::set_width (int width) +{ + if (m_width != width) + { + m_width = width; + render (); + } +} + +void TextBox::set_text (const char * text) +{ + if (strcmp_safe (m_text, text)) + { + m_text = String (text); + render (); + } +} + +void TextBox::set_font (const char * font) +{ + if (font) + { + m_font.capture (qfont_from_string (font)); + m_metrics.capture (new QFontMetrics (* m_font, this)); + } + else + { + m_font.clear (); + m_metrics.clear (); + } + + render (); +} + +void TextBox::set_scroll (bool scroll) +{ + if (m_may_scroll != scroll || m_two_way != config.twoway_scroll) + { + m_may_scroll = scroll; + m_two_way = config.twoway_scroll; + render (); + } +} + +TextBox::~TextBox () +{ + int idx = textboxes.find (this); + if (idx >= 0) + textboxes.remove (idx, 1); +} + +TextBox::TextBox (int width, const char * font, bool scroll) : + m_width (width), + m_may_scroll (scroll), + m_two_way (config.twoway_scroll) +{ + /* size is computed by set_font() */ + add_input (1, 1, false, true); + set_font (font); + + textboxes.append (this); +} + +void TextBox::update_all () +{ + for (TextBox * textbox : textboxes) + textbox->render (); +} diff --git a/src/skins-qt/textbox.h b/src/skins-qt/textbox.h new file mode 100644 index 0000000..6229ff3 --- /dev/null +++ b/src/skins-qt/textbox.h @@ -0,0 +1,82 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2011 John Lindgren + * + * Based on: + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#ifndef SKINS_UI_SKINNED_TEXTBOX_H +#define SKINS_UI_SKINNED_TEXTBOX_H + +#include <libaudcore/hook.h> +#include <libaudcore/objects.h> + +#include "widget.h" + +class QFont; +class QFontMetrics; +class QImage; + +class TextBox : public Widget +{ +public: + TextBox (int width, const char * font, bool scroll); + ~TextBox (); + + void set_width (int width); + const String & get_text () { return m_text; } + void set_text (const char * text); + void set_font (const char * font); + void set_scroll (bool scroll); + + typedef bool (* PressCB) (QMouseEvent *); + void on_press (PressCB callback) { press = callback; } + + static void update_all (); + +private: + virtual void draw (QPainter & cr); + virtual bool button_press (QMouseEvent * event); + + void scroll_timeout (); + void render_vector (const char * text); + void render_bitmap (const char * text); + void render (); + + const Timer<TextBox> + scroll_timer {TimerRate::Hz30, this, & TextBox::scroll_timeout}; + + String m_text; + SmartPtr<QFont> m_font; + SmartPtr<QFontMetrics> m_metrics; + SmartPtr<QImage> m_buf; + + int m_width = 0, m_buf_width = 0; + bool m_may_scroll = false, m_two_way = false; + bool m_scrolling = false, m_backward = false; + int m_offset = 0, m_delay = 0; + + PressCB press = nullptr; +}; + +#endif diff --git a/src/skins-qt/util.cc b/src/skins-qt/util.cc new file mode 100644 index 0000000..8c7badc --- /dev/null +++ b/src/skins-qt/util.cc @@ -0,0 +1,356 @@ +/* Audacious - Cross-platform multimedia player + * Copyright (C) 2005-2009 Audacious development team + * + * Based on BMP: + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <unistd.h> + +#include <glib/gstdio.h> + +#include <libaudcore/audstrings.h> +#include <libaudcore/i18n.h> +#include <libaudcore/hook.h> +#include <libaudcore/multihash.h> +#include <libaudcore/runtime.h> +#include <libaudcore/vfs.h> + +#include "util.h" + +#ifdef S_IRGRP +#define DIRMODE (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) +#else +#define DIRMODE (S_IRWXU) +#endif + +StringBuf find_file_case_path (const char * folder, const char * basename) +{ + static SimpleHash<String, Index<String>> cache; + + String key (folder); + Index<String> * list = cache.lookup (key); + + if (! list) + { + GDir * handle = g_dir_open (folder, 0, nullptr); + if (! handle) + return StringBuf (); + + list = cache.add (key, Index<String> ()); + + const char * name; + while ((name = g_dir_read_name (handle))) + list->append (name); + + g_dir_close (handle); + } + + for (const String & entry : * list) + { + if (! strcmp_nocase (entry, basename)) + return filename_build ({folder, entry}); + } + + return StringBuf (); +} + +VFSFile open_local_file_nocase (const char * folder, const char * basename) +{ + StringBuf path = find_file_case_path (folder, basename); + if (! path) + return VFSFile (); + + StringBuf uri = filename_to_uri (path); + if (! uri) + return VFSFile (); + + return VFSFile (uri, "r"); +} + +StringBuf skin_pixmap_locate (const char * folder, const char * basename, const char * altname) +{ + static const char * const exts[] = {".bmp", ".png", ".xpm"}; + + for (const char * ext : exts) + { + StringBuf name = str_concat({basename, ext}); + name.steal (find_file_case_path (folder, name)); + + if (name) + return name; + } + + return altname ? skin_pixmap_locate (folder, altname) : StringBuf (); +} + +char * text_parse_line (char * text) +{ + char * newline = strchr (text, '\n'); + + if (newline == nullptr) + return nullptr; + + * newline = 0; + return newline + 1; +} + +enum ArchiveType { + ARCHIVE_UNKNOWN = 0, + ARCHIVE_TAR, + ARCHIVE_TGZ, + ARCHIVE_ZIP, + ARCHIVE_TBZ2 +}; + +typedef StringBuf (* ArchiveExtractFunc) (const char *, const char *); + +struct ArchiveExtensionType { + ArchiveType type; + const char *ext; +}; + +static ArchiveExtensionType archive_extensions[] = { + {ARCHIVE_TAR, ".tar"}, + {ARCHIVE_ZIP, ".wsz"}, + {ARCHIVE_ZIP, ".zip"}, + {ARCHIVE_TGZ, ".tar.gz"}, + {ARCHIVE_TGZ, ".tgz"}, + {ARCHIVE_TBZ2, ".tar.bz2"}, + {ARCHIVE_TBZ2, ".bz2"} +}; + +static StringBuf archive_extract_tar (const char * archive, const char * dest); +static StringBuf archive_extract_zip (const char * archive, const char * dest); +static StringBuf archive_extract_tgz (const char * archive, const char * dest); +static StringBuf archive_extract_tbz2 (const char * archive, const char * dest); + +static ArchiveExtractFunc archive_extract_funcs[] = { + nullptr, + archive_extract_tar, + archive_extract_tgz, + archive_extract_zip, + archive_extract_tbz2 +}; + +/* FIXME: these functions can be generalised into a function using a + * command lookup table */ + +static const char * get_tar_command () +{ + static const char * command = nullptr; + + if (! command) + { + if (! (command = getenv("TARCMD"))) + command = "tar"; + } + + return command; +} + +static const char * get_unzip_command () +{ + static const char * command = nullptr; + + if (! command) + { + if (! (command = getenv("UNZIPCMD"))) + command = "unzip"; + } + + return command; +} + +static StringBuf archive_extract_tar (const char * archive, const char * dest) +{ + return str_printf ("%s >/dev/null xf \"%s\" -C %s", get_tar_command (), archive, dest); +} + +static StringBuf archive_extract_zip (const char * archive, const char * dest) +{ + return str_printf ("%s >/dev/null -o -j \"%s\" -d %s", get_unzip_command (), archive, dest); +} + +static StringBuf archive_extract_tgz (const char * archive, const char * dest) +{ + return str_printf ("%s >/dev/null xzf \"%s\" -C %s", get_tar_command (), archive, dest); +} + +static StringBuf archive_extract_tbz2 (const char * archive, const char * dest) +{ + return str_printf ("bzip2 -dc \"%s\" | %s >/dev/null xf - -C %s", archive, + get_tar_command (), dest); +} + +static ArchiveType archive_get_type (const char * filename) +{ + for (auto & ext : archive_extensions) + { + if (str_has_suffix_nocase (filename, ext.ext)) + return ext.type; + } + + return ARCHIVE_UNKNOWN; +} + +bool file_is_archive (const char * filename) +{ + return (archive_get_type (filename) != ARCHIVE_UNKNOWN); +} + +StringBuf archive_basename (const char * str) +{ + for (auto & ext : archive_extensions) + { + if (str_has_suffix_nocase (str, ext.ext)) + return str_copy (str, strlen (str) - strlen (ext.ext)); + } + + return StringBuf (); +} + +/** + * Escapes characters that are special to the shell inside double quotes. + * + * @param string String to be escaped. + * @return Given string with special characters escaped. + */ +static StringBuf escape_shell_chars (const char * string) +{ + const char *special = "$`\"\\"; /* Characters to escape */ + + int num = 0; + for (const char * in = string; * in; in ++) + { + if (strchr (special, * in)) + num ++; + } + + StringBuf escaped (strlen (string) + num); + + char * out = escaped; + for (const char * in = string; * in; in ++) + { + if (strchr (special, * in)) + * out ++ = '\\'; + * out ++ = * in; + } + + return escaped; +} + +/** + * Decompresses the archive "filename" to a temporary directory, + * returns the path to the temp dir, or nullptr if failed + */ +StringBuf archive_decompress (const char * filename) +{ + ArchiveType type = archive_get_type (filename); + if (type == ARCHIVE_UNKNOWN) + return StringBuf (); + + StringBuf tmpdir = filename_build ({g_get_tmp_dir (), "audacious.XXXXXX"}); + if (! g_mkdtemp (tmpdir)) + { + AUDWARN ("Error creating %s: %s\n", strerror (errno)); + return StringBuf (); + } + + StringBuf escaped_filename = escape_shell_chars (filename); + StringBuf cmd = archive_extract_funcs[type] (escaped_filename, tmpdir); + + AUDDBG ("Executing \"%s\"\n", (const char *) cmd); + int ret = system (cmd); + if (ret != 0) + { + AUDDBG ("Command \"%s\" returned error %d\n", (const char *) cmd, ret); + return StringBuf (); + } + + return tmpdir; +} + +static void del_directory_func (const char * path, const char *) +{ + if (g_file_test (path, G_FILE_TEST_IS_DIR)) + del_directory (path); + else + g_unlink (path); +} + +void del_directory (const char * path) +{ + dir_foreach (path, del_directory_func); + g_rmdir (path); +} + +Index<int> string_to_int_array (const char * str) +{ + Index<int> array; + int temp; + const char * ptr = str; + char * endptr; + + for (;;) + { + temp = strtol (ptr, &endptr, 10); + if (ptr == endptr) + break; + array.append (temp); + ptr = endptr; + while (! g_ascii_isdigit ((int) * ptr) && (* ptr) != '\0') + ptr ++; + if (* ptr == '\0') + break; + } + + return array; +} + +bool dir_foreach (const char * path, DirForeachFunc func) +{ + GError * error = nullptr; + GDir * dir = g_dir_open (path, 0, & error); + if (! dir) + { + AUDWARN ("Error reading %s: %s\n", path, error->message); + g_error_free (error); + return false; + } + + const char * entry; + while ((entry = g_dir_read_name (dir))) + func (filename_build ({path, entry}), entry); + + g_dir_close (dir); + return true; +} + +void make_directory (const char * path) +{ + if (g_mkdir_with_parents (path, DIRMODE) != 0) + AUDWARN ("Error creating %s: %s\n", strerror (errno)); +} diff --git a/src/skins-qt/util.h b/src/skins-qt/util.h new file mode 100644 index 0000000..8a651ed --- /dev/null +++ b/src/skins-qt/util.h @@ -0,0 +1,52 @@ +/* Audacious - Cross-platform multimedia player + * Copyright (C) 2005-2009 Audacious development team + * + * Based on BMP: + * Copyright (C) 2003-2004 BMP development team + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#ifndef UTIL_H +#define UTIL_H + +#include <libaudcore/vfs.h> + +typedef void (* DirForeachFunc) (const char * path, const char * basename); + +StringBuf find_file_case_path (const char * folder, const char * basename); + +VFSFile open_local_file_nocase (const char * folder, const char * basename); +StringBuf skin_pixmap_locate (const char * folder, const char * basename, + const char * altname = nullptr); + +char * text_parse_line (char * text); + +void make_directory (const char * path); +void del_directory (const char * path); + +bool dir_foreach (const char * path, DirForeachFunc func); + +Index<int> string_to_int_array (const char *str); + +bool file_is_archive (const char * filename); +StringBuf archive_basename (const char * str); +StringBuf archive_decompress (const char * path); + +#endif diff --git a/src/skins-qt/view.cc b/src/skins-qt/view.cc new file mode 100644 index 0000000..44dea39 --- /dev/null +++ b/src/skins-qt/view.cc @@ -0,0 +1,291 @@ +/* + * view.c + * Copyright 2014-2015 John Lindgren + * + * This file is part of Audacious. + * + * Audacious 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, version 2 or version 3 of the License. + * + * Audacious 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 + * Audacious. If not, see <http://www.gnu.org/licenses/>. + * + * The Audacious team does not consider modular code linking to Audacious or + * using our public API to be a derived work. + */ + +#include "view.h" + +#include <libaudcore/hook.h> +#include <libaudcore/mainloop.h> +#include <libaudcore/runtime.h> + +#include <QWindow> + +#include "plugin.h" +#include "plugin-window.h" +#include "skins_cfg.h" +#include "equalizer.h" +#include "main.h" +#include "vis-callbacks.h" +#include "playlist.h" +#include "button.h" +#include "eq-graph.h" +#include "textbox.h" +#include "menurow.h" +#include "window.h" +#include "vis.h" + +void view_show_player (bool show) +{ + if (show) + { + mainwin->show (); + mainwin->activateWindow (); + show_plugin_windows (); + } + else + { + mainwin->hide (); + hide_plugin_windows (); + } + + view_apply_show_playlist (); + view_apply_show_equalizer (); + + start_stop_visual (false); +} + +void view_set_show_playlist (bool show) +{ + aud_set_bool ("skins", "playlist_visible", show); + hook_call ("skins set playlist_visible", nullptr); + + view_apply_show_playlist (); +} + +void view_apply_show_playlist () +{ + bool show = aud_get_bool ("skins", "playlist_visible"); + + if (show && mainwin->isVisible ()) + { + playlistwin->winId (); + playlistwin->windowHandle ()->setTransientParent (mainwin->windowHandle ()); + playlistwin->show (); + playlistwin->activateWindow (); + } + else + playlistwin->hide (); + + mainwin_pl->set_active (show); +} + +void view_set_show_equalizer (bool show) +{ + aud_set_bool ("skins", "equalizer_visible", show); + hook_call ("skins set equalizer_visible", nullptr); + + view_apply_show_equalizer (); +} + +void view_apply_show_equalizer () +{ + bool show = aud_get_bool ("skins", "equalizer_visible"); + + if (show && mainwin->isVisible ()) + { + equalizerwin->winId (); + equalizerwin->windowHandle ()->setTransientParent (mainwin->windowHandle ()); + equalizerwin->show (); + equalizerwin->activateWindow (); + } + else + equalizerwin->hide (); + + mainwin_eq->set_active (show); +} + +void view_set_player_shaded (bool shaded) +{ + aud_set_bool ("skins", "player_shaded", shaded); + hook_call ("skins set player_shaded", nullptr); + + view_apply_player_shaded (); +} + +void view_apply_player_shaded () +{ + bool shaded = aud_get_bool ("skins", "player_shaded"); + + mainwin->set_shaded (shaded); + + int width = shaded ? MAINWIN_SHADED_WIDTH : skin.hints.mainwin_width; + int height = shaded ? MAINWIN_SHADED_HEIGHT : skin.hints.mainwin_height; + mainwin->resize (width, height); + + if (config.autoscroll) + mainwin_info->set_scroll (! shaded); +} + +void view_set_playlist_shaded (bool shaded) +{ + aud_set_bool ("skins", "playlist_shaded", shaded); + hook_call ("skins set playlist_shaded", nullptr); + + view_apply_playlist_shaded (); +} + +void view_apply_playlist_shaded () +{ + bool shaded = aud_get_bool ("skins", "playlist_shaded"); + + playlistwin->set_shaded (shaded); + + int height = shaded ? MAINWIN_SHADED_HEIGHT : config.playlist_height; + playlistwin->resize (config.playlist_width, height); + + if (config.autoscroll) + playlistwin_sinfo->set_scroll (shaded); +} + +void view_set_equalizer_shaded (bool shaded) +{ + aud_set_bool ("skins", "equalizer_shaded", shaded); + hook_call ("skins set equalizer_shaded", nullptr); + + view_apply_equalizer_shaded (); +} + +void view_apply_equalizer_shaded () +{ + bool shaded = aud_get_bool ("skins", "equalizer_shaded"); + + /* do not allow shading the equalizer if eq_ex.bmp is missing */ + if (skin.pixmaps[SKIN_EQ_EX].isNull ()) + shaded = false; + + equalizerwin->set_shaded (shaded); + equalizerwin->resize (275, shaded ? 14 : 116); +} + +void view_set_double_size (bool double_size) +{ + aud_set_bool ("skins", "double_size", double_size); + hook_call ("skins set double_size", nullptr); + + view_apply_double_size (); +} + +void view_apply_double_size () +{ + static QueuedFunc restart; + restart.queue ((QueuedFunc::Func) skins_restart, nullptr); +} + +void view_set_on_top (bool on_top) +{ + aud_set_bool ("skins", "always_on_top", on_top); + hook_call ("skins set always_on_top", nullptr); + + view_apply_on_top (); +} + +void view_apply_on_top () +{ +#if 0 + bool on_top = aud_get_bool ("skins", "always_on_top"); + + gtk_window_set_keep_above ((GtkWindow *) mainwin->gtk (), on_top); + gtk_window_set_keep_above ((GtkWindow *) equalizerwin->gtk (), on_top); + gtk_window_set_keep_above ((GtkWindow *) playlistwin->gtk (), on_top); +#endif + + mainwin_menurow->refresh (); +} + +void view_set_sticky (bool sticky) +{ + aud_set_bool ("skins", "sticky", sticky); + hook_call ("skins set sticky", nullptr); + + view_apply_sticky (); +} + +void view_apply_sticky () +{ +#if 0 + bool sticky = aud_get_bool ("skins", "sticky"); + + if (sticky) + { + gtk_window_stick ((GtkWindow *) mainwin->gtk ()); + gtk_window_stick ((GtkWindow *) equalizerwin->gtk ()); + gtk_window_stick ((GtkWindow *) playlistwin->gtk ()); + } + else + { + gtk_window_unstick ((GtkWindow *) mainwin->gtk ()); + gtk_window_unstick ((GtkWindow *) equalizerwin->gtk ()); + gtk_window_unstick ((GtkWindow *) playlistwin->gtk ()); + } +#endif +} + +void view_set_show_remaining (bool remaining) +{ + aud_set_bool ("skins", "show_remaining_time", remaining); + hook_call ("skins set show_remaining_time", nullptr); + + view_apply_show_remaining (); +} + +void view_apply_show_remaining () +{ + mainwin_update_song_info (); +} + +static QRegion * scale_mask (const Index<QRect> & mask, int scale) +{ + QRegion * region = nullptr; + + for (auto & rect : mask) + { + QRect scaled ( + rect.x () * scale, + rect.y () * scale, + rect.width () * scale, + rect.height () * scale + ); + + if (region) + * region |= scaled; + else + region = new QRegion (scaled); + } + + return region; +} + +void view_apply_skin () +{ + mainwin->set_shapes + (scale_mask (skin.masks[SKIN_MASK_MAIN], config.scale), + scale_mask (skin.masks[SKIN_MASK_MAIN_SHADE], config.scale)); + equalizerwin->set_shapes + (scale_mask (skin.masks[SKIN_MASK_EQ], config.scale), + scale_mask (skin.masks[SKIN_MASK_EQ_SHADE], config.scale)); + + mainwin_refresh_hints (); + view_apply_equalizer_shaded (); + TextBox::update_all (); + + mainwin->queue_draw (); + equalizerwin->queue_draw (); + playlistwin->queue_draw (); +} diff --git a/src/skins-qt/view.h b/src/skins-qt/view.h new file mode 100644 index 0000000..227645d --- /dev/null +++ b/src/skins-qt/view.h @@ -0,0 +1,56 @@ +/* + * view.h + * Copyright 2014 John Lindgren + * + * This file is part of Audacious. + * + * Audacious 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, version 2 or version 3 of the License. + * + * Audacious 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 + * Audacious. If not, see <http://www.gnu.org/licenses/>. + * + * The Audacious team does not consider modular code linking to Audacious or + * using our public API to be a derived work. + */ + +#ifndef SKINS_VIEW_H +#define SKINS_VIEW_H + +void view_show_player (bool show); + +void view_set_show_playlist (bool show); +void view_apply_show_playlist (); + +void view_set_show_equalizer (bool show); +void view_apply_show_equalizer (); + +void view_set_player_shaded (bool shaded); +void view_apply_player_shaded (); + +void view_set_playlist_shaded (bool shaded); +void view_apply_playlist_shaded (); + +void view_set_equalizer_shaded (bool shaded); +void view_apply_equalizer_shaded (); + +void view_set_double_size (bool double_size); +void view_apply_double_size (); + +void view_set_on_top (bool on_top); +void view_apply_on_top (); + +void view_set_sticky (bool sticky); +void view_apply_sticky (); + +void view_set_show_remaining (bool remaining); +void view_apply_show_remaining (); + +void view_apply_skin (); + +#endif /* SKINS_VIEW_H */ diff --git a/src/skins/ui_main_evlisteners.cc b/src/skins-qt/vis-callbacks.cc index 564400b..a78b9c8 100644 --- a/src/skins/ui_main_evlisteners.cc +++ b/src/skins-qt/vis-callbacks.cc @@ -27,101 +27,17 @@ #include <libaudcore/runtime.h> #include "skins_cfg.h" -#include "ui_main.h" -#include "ui_main_evlisteners.h" -#include "ui_skin.h" -#include "ui_skinned_button.h" -#include "ui_skinned_playstatus.h" -#include "ui_vis.h" +#include "main.h" +#include "vis-callbacks.h" +#include "skin.h" +#include "button.h" +#include "hslider.h" +#include "number.h" +#include "playstatus.h" +#include "textbox.h" +#include "vis.h" #include "util.h" -static void title_change (void) -{ - if (aud_drct_get_ready ()) - mainwin_set_song_title (aud_drct_get_title ()); - else - mainwin_set_song_title ("Buffering ..."); -} - -static void info_change (void) -{ - int bitrate, samplerate, channels; - aud_drct_get_info (bitrate, samplerate, channels); - mainwin_set_song_info (bitrate, samplerate, channels); -} - -static void -ui_main_evlistener_hide_seekbar(void * hook_data, void * user_data) -{ - mainwin_disable_seekbar(); -} - -void ui_main_evlistener_playback_begin (void * hook_data, void * user_data) -{ - mainwin_disable_seekbar(); - mainwin_update_song_info(); - - gtk_widget_show (mainwin_stime_min); - gtk_widget_show (mainwin_stime_sec); - gtk_widget_show (mainwin_minus_num); - gtk_widget_show (mainwin_10min_num); - gtk_widget_show (mainwin_min_num); - gtk_widget_show (mainwin_10sec_num); - gtk_widget_show (mainwin_sec_num); - - if (aud_drct_get_ready () && aud_drct_get_length () > 0) - { - gtk_widget_show (mainwin_position); - gtk_widget_show (mainwin_sposition); - } - - ui_skinned_playstatus_set_status(mainwin_playstatus, STATUS_PLAY); - - title_change (); - info_change (); -} - -static void -ui_main_evlistener_playback_stop(void * hook_data, void * user_data) -{ - mainwin_clear_song_info (); -} - -static void repeat_toggled (void * data, void * user) -{ - button_set_active (mainwin_repeat, aud_get_bool (nullptr, "repeat")); -} - -static void shuffle_toggled (void * data, void * user) -{ - button_set_active (mainwin_shuffle, aud_get_bool (nullptr, "shuffle")); -} - -static void no_advance_toggled (void * data, void * user) -{ - if (aud_get_bool (nullptr, "no_playlist_advance")) - mainwin_show_status_message (_("Single mode.")); - else - mainwin_show_status_message (_("Playlist mode.")); -} - -static void stop_after_song_toggled (void * hook_data, void * user_data) -{ - if (aud_get_bool (nullptr, "stop_after_current_song")) - mainwin_show_status_message (_("Stopping after song.")); -} - -void ui_main_evlistener_playback_pause (void * hook_data, void * user_data) -{ - ui_skinned_playstatus_set_status(mainwin_playstatus, STATUS_PAUSE); -} - -static void -ui_main_evlistener_playback_unpause(void * hook_data, void * user_data) -{ - ui_skinned_playstatus_set_status(mainwin_playstatus, STATUS_PLAY); -} - class VisCallbacks : public Visualizer { public: @@ -136,8 +52,8 @@ public: void VisCallbacks::clear () { - ui_vis_clear_data (mainwin_vis); - ui_svis_clear_data (mainwin_svis); + mainwin_vis->clear (); + mainwin_svis->clear (); } void VisCallbacks::render_mono_pcm (const float * pcm) @@ -156,9 +72,9 @@ void VisCallbacks::render_mono_pcm (const float * pcm) } if (aud_get_bool ("skins", "player_shaded")) - ui_svis_timeout_func (mainwin_svis, data); + mainwin_svis->render (data); else - ui_vis_timeout_func (mainwin_vis, data); + mainwin_vis->render (data); } /* calculate peak dB level, where 1 is 0 dB */ @@ -194,20 +110,20 @@ void VisCallbacks::render_multi_pcm (const float * pcm, int channels) else data[1] = data[0]; - ui_svis_timeout_func (mainwin_svis, data); + mainwin_svis->render (data); } /* convert linear frequency graph to logarithmic one */ -static void make_log_graph (const float * freq, int bands, int db_range, int - int_range, unsigned char * graph) +static void make_log_graph (const float * freq, int bands, int db_range, + int int_range, unsigned char * graph) { static int last_bands = 0; - static float * xscale = nullptr; + static Index<float> xscale; /* conversion table for the x-axis */ if (bands != last_bands) { - xscale = g_renew (float, xscale, bands + 1); + xscale.resize (bands + 1); for (int i = 0; i <= bands; i ++) xscale[i] = powf (256, (float) i / bands) - 0.5f; @@ -277,57 +193,17 @@ void VisCallbacks::render_freq (const float * freq) return; if (shaded) - ui_svis_timeout_func (mainwin_svis, data); + mainwin_svis->render (data); else - ui_vis_timeout_func (mainwin_vis, data); -} - -void -ui_main_evlistener_init(void) -{ - hook_associate("hide seekbar", ui_main_evlistener_hide_seekbar, nullptr); - hook_associate("playback begin", ui_main_evlistener_playback_begin, nullptr); - hook_associate("playback ready", ui_main_evlistener_playback_begin, nullptr); - hook_associate("playback stop", ui_main_evlistener_playback_stop, nullptr); - hook_associate("playback pause", ui_main_evlistener_playback_pause, nullptr); - hook_associate("playback unpause", ui_main_evlistener_playback_unpause, nullptr); - hook_associate ("title change", (HookFunction) title_change, nullptr); - hook_associate ("info change", (HookFunction) info_change, nullptr); - - hook_associate("playback seek", (HookFunction) mainwin_update_song_info, nullptr); - - hook_associate ("set repeat", repeat_toggled, nullptr); - hook_associate ("set shuffle", shuffle_toggled, nullptr); - hook_associate ("set no_playlist_advance", no_advance_toggled, nullptr); - hook_associate ("set stop_after_current_song", stop_after_song_toggled, nullptr); -} - -void -ui_main_evlistener_dissociate(void) -{ - hook_dissociate("hide seekbar", ui_main_evlistener_hide_seekbar); - hook_dissociate("playback begin", ui_main_evlistener_playback_begin); - hook_dissociate("playback ready", ui_main_evlistener_playback_begin); - hook_dissociate("playback stop", ui_main_evlistener_playback_stop); - hook_dissociate("playback pause", ui_main_evlistener_playback_pause); - hook_dissociate("playback unpause", ui_main_evlistener_playback_unpause); - hook_dissociate ("title change", (HookFunction) title_change); - hook_dissociate ("info change", (HookFunction) info_change); - - hook_dissociate("playback seek", (HookFunction) mainwin_update_song_info); - - hook_dissociate ("set repeat", repeat_toggled); - hook_dissociate ("set shuffle", shuffle_toggled); - hook_dissociate ("set no_playlist_advance", no_advance_toggled); - hook_dissociate ("set stop_after_current_song", stop_after_song_toggled); + mainwin_vis->render (data); } -void start_stop_visual (gboolean exiting) +void start_stop_visual (bool exiting) { static VisCallbacks callbacks; static bool started = false; - if (config.vis_type != VIS_OFF && ! exiting && gtk_widget_get_visible (mainwin)) + if (config.vis_type != VIS_OFF && ! exiting && aud_ui_is_shown ()) { if (! started) { diff --git a/src/skins/ui_main_evlisteners.h b/src/skins-qt/vis-callbacks.h index 04c49dc..56addbc 100644 --- a/src/skins/ui_main_evlisteners.h +++ b/src/skins-qt/vis-callbacks.h @@ -18,17 +18,9 @@ * Audacious or using our public API to be a derived work. */ -#include <glib.h> - #ifndef SKINS_UI_MAIN_EVLISTENERS_H #define SKINS_UI_MAIN_EVLISTENERS_H -void ui_main_evlistener_init(void); -void ui_main_evlistener_dissociate(void); - -void ui_main_evlistener_playback_begin (void * hook_data, void * user_data); -void ui_main_evlistener_playback_pause (void * hook_data, void * user_data); - -void start_stop_visual (gboolean exiting); +void start_stop_visual (bool exiting); #endif /* SKINS_UI_MAIN_EVLISTENERS_H */ diff --git a/src/skins-qt/vis.cc b/src/skins-qt/vis.cc new file mode 100644 index 0000000..0d94d81 --- /dev/null +++ b/src/skins-qt/vis.cc @@ -0,0 +1,318 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007-2011 Audacious development team. + * + * Based on: + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include <string.h> +#include <libaudcore/objects.h> + +#include "skins_cfg.h" +#include "skin.h" +#include "vis.h" + +static const float vis_afalloff_speeds[] = {0.34, 0.5, 1.0, 1.3, 1.6}; +static const float vis_pfalloff_speeds[] = {1.2, 1.3, 1.4, 1.5, 1.6}; +static const int vis_scope_colors[16] = {22, 22, 21, 21, 20, 10, 19, 19, 18, + 19, 19, 20, 20, 21, 21, 22}; + +#define RGB_SEEK(x,y) (set = rgb + 76 * (y) + (x)) +#define RGB_SET(c) (* set ++ = (c)) +#define RGB_SET_Y(c) do {* set = (c); set += 76;} while (0) +#define RGB_SET_INDEX(c) RGB_SET (skin.vis_colors[c]) +#define RGB_SET_INDEX_Y(c) RGB_SET_Y (skin.vis_colors[c]) + +void SkinnedVis::set_colors () +{ + uint32_t fgc = skin.colors[SKIN_TEXTFG]; + uint32_t bgc = skin.colors[SKIN_TEXTBG]; + int fg[3] = {qRed (fgc), qGreen (fgc), qBlue (fgc)}; + int bg[3] = {qRed (bgc), qGreen (bgc), qBlue (bgc)}; + + for (int x = 0; x < 256; x ++) + { + unsigned char c[3]; + for (int n = 0; n < 3; n ++) + c[n] = bg[n] + (fg[n] - bg[n]) * x / 255; + m_voice_color[x] = qRgb (c[0], c[1], c[2]); + } + + for (int x = 0; x < 256; x ++) + { + unsigned char r = aud::min (x, 127) * 2; + unsigned char g = aud::clamp (x - 64, 0, 127) * 2; + unsigned char b = aud::max (x - 128, 0) * 2; + m_voice_color_fire[x] = qRgb (r, g, b); + } + + for (int x = 0; x < 256; x ++) + m_voice_color_ice[x] = qRgb (x / 2, x, aud::min (x * 2, 255)); + + uint32_t * set = m_pattern_fill; + uint32_t * end = set + 76; + + while (set < end) + RGB_SET_INDEX (0); + + end = set + 76; + + while (set < end) + { + RGB_SET_INDEX (1); + RGB_SET_INDEX (0); + } +} + +void SkinnedVis::draw (QPainter & cr) +{ + uint32_t rgb[76 * 16]; + uint32_t * set; + + if (config.vis_type != VIS_VOICEPRINT) + { + for (set = rgb; set < rgb + 76 * 16; set += 76 * 2) + memcpy (set, m_pattern_fill, sizeof m_pattern_fill); + } + + switch (config.vis_type) + { + case VIS_ANALYZER: + { + bool bars = (config.analyzer_type == ANALYZER_BARS); + + for (int x = 0; x < 75; x ++) + { + if (bars && (x & 3) == 3) + continue; + + int h = m_data[bars ? (x >> 2) : x]; + h = aud::clamp (h, 0, 16); + RGB_SEEK (x, 16 - h); + + switch (config.analyzer_mode) + { + case ANALYZER_NORMAL: + for (int y = 0; y < h; y ++) + RGB_SET_INDEX_Y (18 - h + y); + break; + case ANALYZER_FIRE: + for (int y = 0; y < h; y ++) + RGB_SET_INDEX_Y (2 + y); + break; + default: /* ANALYZER_VLINES */ + for (int y = 0; y < h; y ++) + RGB_SET_INDEX_Y (18 - h); + break; + } + + if (config.analyzer_peaks) + { + int h = m_peak[bars ? (x >> 2) : x]; + h = aud::clamp (h, 0, 16); + + if (h) + { + RGB_SEEK (x, 16 - h); + RGB_SET_INDEX (23); + } + } + } + + break; + } + case VIS_VOICEPRINT: + { + if (m_voiceprint_advance) + { + m_voiceprint_advance = false; + memmove (m_voiceprint_data, m_voiceprint_data + 1, sizeof + m_voiceprint_data - 1); + + for (int y = 0; y < 16; y ++) + m_voiceprint_data[76 * y + 75] = m_data[y]; + } + + unsigned char * get = m_voiceprint_data; + uint32_t * colors = (config.voiceprint_mode == VOICEPRINT_NORMAL) ? + m_voice_color : (config.voiceprint_mode == VOICEPRINT_FIRE) ? + m_voice_color_fire : /* VOICEPRINT_ICE */ m_voice_color_ice; + set = rgb; + + for (int y = 0; y < 16; y ++) + for (int x = 0; x < 76; x ++) + RGB_SET (colors[* get ++]); + break; + } + case VIS_SCOPE: + if (! m_active) + goto DRAW; + + switch (config.scope_mode) + { + case SCOPE_DOT: + for (int x = 0; x < 75; x ++) + { + int h = aud::clamp ((int) m_data[x], 0, 15); + RGB_SEEK (x, h); + RGB_SET_INDEX (vis_scope_colors[h]); + } + break; + case SCOPE_LINE: + { + for (int x = 0; x < 74; x ++) + { + int h = aud::clamp ((int) m_data[x], 0, 15); + int h2 = aud::clamp ((int) m_data[x + 1], 0, 15); + + if (h < h2) + h2 --; + else if (h > h2) + { + int temp = h; + h = h2 + 1; + h2 = temp; + } + + RGB_SEEK (x, h); + + for (int y = h; y <= h2; y ++) + RGB_SET_INDEX_Y (vis_scope_colors[y]); + } + + int h = aud::clamp ((int) m_data[74], 0, 15); + RGB_SEEK (74, h); + RGB_SET_INDEX (vis_scope_colors[h]); + break; + } + default: /* SCOPE_SOLID */ + for (int x = 0; x < 75; x ++) + { + int h = aud::clamp ((int) m_data[x], 0, 15); + int h2; + + if (h < 8) + h2 = 8; + else + { + h2 = h; + h = 8; + } + + RGB_SEEK (x, h); + + for (int y = h; y <= h2; y ++) + RGB_SET_INDEX_Y (vis_scope_colors[y]); + } + break; + } + break; + } + +DRAW: + QImage image ((unsigned char *) rgb, 76, 16, 4 * 76, QImage::Format_RGB32); + cr.drawImage (0, 0, image); +} + +SkinnedVis::SkinnedVis () +{ + set_scale (config.scale); + add_drawable (76, 16); + clear (); +} + +void SkinnedVis::clear () +{ + m_active = false; + m_voiceprint_advance = false; + + memset (m_data, 0, sizeof m_data); + memset (m_peak, 0, sizeof m_peak); + memset (m_peak_speed, 0, sizeof m_peak_speed); + memset (m_voiceprint_data, 0, sizeof m_voiceprint_data); + + queue_draw (); +} + +void SkinnedVis::render (const unsigned char * data) +{ + if (config.vis_type == VIS_ANALYZER) + { + const int n = (config.analyzer_type == ANALYZER_BARS) ? 19 : 75; + + for (int i = 0; i < n; i ++) + { + if (data[i] > m_data[i]) + { + m_data[i] = data[i]; + if (m_data[i] > m_peak[i]) + { + m_peak[i] = m_data[i]; + m_peak_speed[i] = 0.01; + + } + else if (m_peak[i] > 0.0) + { + m_peak[i] -= m_peak_speed[i]; + m_peak_speed[i] *= vis_pfalloff_speeds[config.peaks_falloff]; + if (m_peak[i] < m_data[i]) + m_peak[i] = m_data[i]; + if (m_peak[i] < 0.0) + m_peak[i] = 0.0; + } + } + else + { + if (m_data[i] > 0.0) + { + m_data[i] -= vis_afalloff_speeds[config.analyzer_falloff]; + if (m_data[i] < 0.0) + m_data[i] = 0.0; + } + if (m_peak[i] > 0.0) + { + m_peak[i] -= m_peak_speed[i]; + m_peak_speed[i] *= vis_pfalloff_speeds[config.peaks_falloff]; + if (m_peak[i] < m_data[i]) + m_peak[i] = m_data[i]; + if (m_peak[i] < 0.0) + m_peak[i] = 0.0; + } + } + } + } + else if (config.vis_type == VIS_VOICEPRINT) + { + for (int i = 0; i < 16; i ++) + m_data[i] = data[15 - i]; + + m_voiceprint_advance = true; + } + else + { + for (int i = 0; i < 75; i ++) + m_data[i] = data[i]; + } + + m_active = true; + draw_now (); +} diff --git a/src/skins-qt/vis.h b/src/skins-qt/vis.h new file mode 100644 index 0000000..b049747 --- /dev/null +++ b/src/skins-qt/vis.h @@ -0,0 +1,90 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007-2011 Audacious development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#ifndef SKINS_UI_VIS_H +#define SKINS_UI_VIS_H + +#include <stdint.h> +#include "widget.h" + +typedef enum { + VIS_ANALYZER, VIS_SCOPE, VIS_VOICEPRINT, VIS_OFF +} VisType; + +typedef enum { + ANALYZER_NORMAL, ANALYZER_FIRE, ANALYZER_VLINES +} AnalyzerMode; + +typedef enum { + ANALYZER_LINES, ANALYZER_BARS +} AnalyzerType; + +typedef enum { + SCOPE_DOT, SCOPE_LINE, SCOPE_SOLID +} ScopeMode; + +typedef enum { + VOICEPRINT_NORMAL, VOICEPRINT_FIRE, VOICEPRINT_ICE +} VoiceprintMode; + +typedef enum { + VU_NORMAL, VU_SMOOTH +} VUMode; + +typedef enum { + FALLOFF_SLOWEST, FALLOFF_SLOW, FALLOFF_MEDIUM, FALLOFF_FAST, FALLOFF_FASTEST +} FalloffSpeed; + +class SkinnedVis : public Widget +{ +public: + SkinnedVis (); + void set_colors (); + void clear (); + void render (const unsigned char * data); + +private: + void draw (QPainter & cr); + + uint32_t m_voice_color[256]; + uint32_t m_voice_color_fire[256]; + uint32_t m_voice_color_ice[256]; + uint32_t m_pattern_fill[76 * 2]; + + bool m_active, m_voiceprint_advance; + float m_data[75], m_peak[75], m_peak_speed[75]; + unsigned char m_voiceprint_data[76 * 16]; +}; + +class SmallVis : public Widget +{ +public: + SmallVis (); + void clear (); + void render (const unsigned char * data); + +private: + void draw (QPainter & cr); + + bool m_active; + int m_data[75]; +}; + +#endif diff --git a/src/skins/ui_skinned_window.h b/src/skins-qt/widget.cc index eb73db6..0db35ce 100644 --- a/src/skins/ui_skinned_window.h +++ b/src/skins-qt/widget.cc @@ -1,6 +1,6 @@ /* - * ui_skinned_window.h - * Copyright 2011 John Lindgren + * widget.cc + * Copyright 2015 John Lindgren * * This file is part of Audacious. * @@ -19,20 +19,29 @@ * using our public API to be a derived work. */ -#ifndef SKINS_UI_SKINNED_WINDOW_H -#define SKINS_UI_SKINNED_WINDOW_H +#include "widget.h" -#include <gtk/gtk.h> +void Widget::add_input (int width, int height, bool track_motion, bool drawable) +{ + resize (width, height); + setMouseTracking (track_motion); + m_drawable = drawable; +} -GtkWidget * window_new (int * x, int * y, int w, int h, gboolean main, - gboolean shaded, void (* draw) (GtkWidget * window, cairo_t * cr)); -void window_set_size (GtkWidget * window, int w, int h); -void window_set_shapes (GtkWidget * window, GdkRegion * shape, GdkRegion * sshape); -void window_set_shaded (GtkWidget * window, gboolean shaded); -void window_put_widget (GtkWidget * window, gboolean shaded, GtkWidget * widget, - int x, int y); -void window_move_widget (GtkWidget * window, gboolean shaded, GtkWidget * - widget, int x, int y); -void window_show_all (GtkWidget * window); +void Widget::add_drawable (int width, int height) +{ + resize (width, height); + m_drawable = true; +} -#endif +void Widget::paintEvent (QPaintEvent *) +{ + if (m_drawable) + { + QPainter p (this); + if (m_scale != 1) + p.setTransform (QTransform ().scale (m_scale, m_scale)); + + draw (p); + } +} diff --git a/src/skins-qt/widget.h b/src/skins-qt/widget.h new file mode 100644 index 0000000..7d208e9 --- /dev/null +++ b/src/skins-qt/widget.h @@ -0,0 +1,83 @@ +/* + * widget.h + * Copyright 2015 John Lindgren + * + * This file is part of Audacious. + * + * Audacious 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, version 2 or version 3 of the License. + * + * Audacious 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 + * Audacious. If not, see <http://www.gnu.org/licenses/>. + * + * The Audacious team does not consider modular code linking to Audacious or + * using our public API to be a derived work. + */ + +#ifndef SKINS_WIDGET_H +#define SKINS_WIDGET_H + +#include <QCloseEvent> +#include <QKeyEvent> +#include <QMouseEvent> +#include <QPainter> +#include <QWheelEvent> +#include <QWidget> + +class Widget : public QWidget +{ +public: + void queue_draw () { update (); } + +protected: + void add_input (int width, int height, bool track_motion, bool drawable); + void add_drawable (int width, int height); + + void set_scale (int scale) { m_scale = scale; } + void resize (int w, int h) { QWidget::resize (w * m_scale, h * m_scale); } + +#ifdef Q_OS_MAC + /* repaint() causes graphical glitches on OS X + * http://redmine.audacious-media-player.org/issues/558 */ + void draw_now () { update (); } +#else + void draw_now () { repaint (); } +#endif + + virtual void draw (QPainter & cr) {} + virtual bool keypress (QKeyEvent * event) { return false; } + virtual bool button_press (QMouseEvent * event) { return false; } + virtual bool button_release (QMouseEvent * event) { return false; } + virtual bool scroll (QWheelEvent * event) { return false; } + virtual bool motion (QMouseEvent * event) { return false; } + virtual bool leave () { return false; } + virtual bool close () { return false; } + +private: + void paintEvent (QPaintEvent *); + + void keyPressEvent (QKeyEvent * event) + { event->setAccepted (keypress (event)); } + void mousePressEvent (QMouseEvent * event) + { event->setAccepted (button_press (event)); } + void mouseReleaseEvent (QMouseEvent * event) + { event->setAccepted (button_release (event)); } + void wheelEvent (QWheelEvent * event) + { event->setAccepted (scroll (event)); } + void mouseMoveEvent (QMouseEvent * event) + { event->setAccepted (motion (event)); } + void leaveEvent (QEvent * event) + { event->setAccepted (leave ()); } + void closeEvent (QCloseEvent * event) + { event->setAccepted (close ()); } + + bool m_drawable = false; + int m_scale = 1; +}; + +#endif // SKINS_WIDGET_H diff --git a/src/skins-qt/window.cc b/src/skins-qt/window.cc new file mode 100644 index 0000000..c80fd0c --- /dev/null +++ b/src/skins-qt/window.cc @@ -0,0 +1,161 @@ +/* + * ui_skinned_window.c + * Copyright 2011 John Lindgren + * + * This file is part of Audacious. + * + * Audacious 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, version 2 or version 3 of the License. + * + * Audacious 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 + * Audacious. If not, see <http://www.gnu.org/licenses/>. + * + * The Audacious team does not consider modular code linking to Audacious or + * using our public API to be a derived work. + */ + +#include "window.h" +#include "plugin.h" +#include "skins_cfg.h" + +void Window::apply_shape () +{ + QRegion * mask = m_is_shaded ? m_sshape.get () : m_shape.get (); + if (mask) + setMask (* mask); + else + clearMask (); +} + +bool Window::button_press (QMouseEvent * event) +{ + /* pass double clicks through; they are handled elsewhere */ + if (event->button () != Qt::LeftButton || event->type () == QEvent::MouseButtonDblClick) + return false; + + if (m_is_moving) + return true; + + dock_move_start (m_id, event->globalX (), event->globalY ()); + m_is_moving = true; + return true; +} + +bool Window::button_release (QMouseEvent * event) +{ + if (event->button () != Qt::LeftButton) + return false; + + m_is_moving = false; + return true; +} + +bool Window::motion (QMouseEvent * event) +{ + if (! m_is_moving) + return true; + + dock_move (event->globalX (), event->globalY ()); + return true; +} + +bool Window::close () +{ + skins_close (); + return true; +} + +Window::~Window () +{ + dock_remove_window (m_id); +} + +Window::Window (int id, int * x, int * y, int w, int h, bool shaded) : + m_id (id), + m_is_shaded (shaded) +{ + if (id == WINDOW_MAIN) + setWindowFlags (Qt::Window | Qt::FramelessWindowHint); + else + setWindowFlags (Qt::Dialog | Qt::FramelessWindowHint); + + move (* x, * y); + + set_scale (config.scale); + add_input (w, h, true, true); + + w *= config.scale; + h *= config.scale; + setFixedSize (w, h); + + setAttribute (Qt::WA_NoSystemBackground); + + m_normal = new QWidget (this); + m_normal->resize (w, h); + m_shaded = new QWidget (this); + m_shaded->resize (w, h); + + if (shaded) + m_normal->hide (); + else + m_shaded->hide (); + + dock_add_window (id, this, x, y, w, h); +} + +void Window::resize (int w, int h) +{ + Widget::resize (w, h); + + w *= config.scale; + h *= config.scale; + setFixedSize (w, h); + + m_normal->resize (w, h); + m_shaded->resize (w, h); + + dock_set_size (m_id, w, h); +} + +void Window::set_shapes (QRegion * shape, QRegion * sshape) +{ + m_shape.capture (shape); + m_sshape.capture (sshape); + apply_shape (); +} + +void Window::set_shaded (bool shaded) +{ + if (m_is_shaded == shaded) + return; + + if (shaded) + { + m_normal->hide (); + m_shaded->show (); + } + else + { + m_shaded->hide (); + m_normal->show (); + } + + m_is_shaded = shaded; + apply_shape (); +} + +void Window::put_widget (bool shaded, Widget * widget, int x, int y) +{ + widget->setParent (shaded ? m_shaded : m_normal); + widget->move (x * config.scale, y * config.scale); +} + +void Window::move_widget (bool shaded, Widget * widget, int x, int y) +{ + widget->move (x * config.scale, y * config.scale); +} diff --git a/src/skins-qt/window.h b/src/skins-qt/window.h new file mode 100644 index 0000000..a0237d6 --- /dev/null +++ b/src/skins-qt/window.h @@ -0,0 +1,76 @@ +/* + * ui_skinned_window.h + * Copyright 2011 John Lindgren + * + * This file is part of Audacious. + * + * Audacious 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, version 2 or version 3 of the License. + * + * Audacious 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 + * Audacious. If not, see <http://www.gnu.org/licenses/>. + * + * The Audacious team does not consider modular code linking to Audacious or + * using our public API to be a derived work. + */ + +#ifndef SKINS_UI_SKINNED_WINDOW_H +#define SKINS_UI_SKINNED_WINDOW_H + +#include "widget.h" + +#include <libaudcore/objects.h> + +enum { + WINDOW_MAIN, + WINDOW_EQ, + WINDOW_PLAYLIST, + N_WINDOWS +}; + +class Window : public Widget +{ +public: + Window (int id, int * x, int * y, int w, int h, bool shaded); + ~Window (); + + void resize (int w, int h); + void set_shapes (QRegion * shape, QRegion * sshape); + bool is_shaded () { return m_is_shaded; } + void set_shaded (bool shaded); + void put_widget (bool shaded, Widget * widget, int x, int y); + void move_widget (bool shaded, Widget * widget, int x, int y); + + void getPosition (int * xp, int * yp) + { * xp = x (); * yp = y (); } + +protected: + bool keypress (QKeyEvent * event); + bool button_press (QMouseEvent * event); + bool button_release (QMouseEvent * event); + bool motion (QMouseEvent * event); + bool close (); + +private: + void apply_shape (); + + const int m_id; + bool m_is_shaded = false; + bool m_is_moving = false; + QWidget * m_normal = nullptr, * m_shaded = nullptr; + SmartPtr<QRegion> m_shape, m_sshape; +}; + +void dock_add_window (int id, Window * window, int * x, int * y, int w, int h); +void dock_remove_window (int id); +void dock_set_size (int id, int w, int h); +void dock_move_start (int id, int x, int y); +void dock_move (int x, int y); +void dock_change_scale (int old_scale, int new_scale); + +#endif diff --git a/src/skins/Makefile b/src/skins/Makefile index 14710d5..1ef397f 100644 --- a/src/skins/Makefile +++ b/src/skins/Makefile @@ -1,163 +1,42 @@ PLUGIN = skins${PLUGIN_SUFFIX} -SRCS = drag-handle.cc \ +SRCS = actions.cc \ + button.cc \ + dock.cc \ + drag-handle.cc \ + eq-graph.cc \ + eq-slider.cc \ + equalizer.cc \ + hslider.cc \ + main.cc \ + menurow.cc \ menus.cc \ + monostereo.cc \ + number.cc \ + playlist.cc \ + playlist-slider.cc \ + playlist-widget.cc \ + playstatus.cc \ plugin.cc \ plugin-window.cc \ - preset-browser.cc \ - preset-list.cc \ + search-select.cc \ + skin.cc \ + skin-ini.cc \ skins_cfg.cc \ + skinselector.cc \ surface.cc \ - ui_skin.cc \ - ui_skin_load_ini.cc \ - ui_skinned_window.cc \ - ui_dock.cc \ + svis.cc \ + textbox.cc \ util.cc \ - ui_vis.cc \ - ui_svis.cc \ - ui_skinned_menurow.cc \ - ui_skinned_button.cc \ - ui_skinned_textbox.cc \ - ui_skinned_playstatus.cc \ - ui_skinned_monostereo.cc \ - ui_skinned_number.cc \ - ui_skinned_horizontal_slider.cc \ - ui_skinned_equalizer_graph.cc \ - ui_skinned_equalizer_slider.cc \ - ui_skinned_playlist.cc \ - ui_skinned_playlist_slider.cc \ - ui_main.cc \ - ui_equalizer.cc \ - ui_playlist.cc \ - ui_main_evlisteners.cc \ - ui_skinselector.cc \ - view.cc + view.cc \ + vis-callbacks.cc \ + vis.cc \ + widget.cc \ + window.cc include ../../buildsys.mk include ../../extra.mk -# These overrides variables in buildsys.mk and so must come after it. -PACKAGE_NAME = audacious -DATA = Skins/Classic/balance.png \ - Skins/Classic/cbuttons.png \ - Skins/Classic/eq_ex.png \ - Skins/Classic/eqmain.png \ - Skins/Classic/main.png \ - Skins/Classic/monoster.png \ - Skins/Classic/nums_ex.png \ - Skins/Classic/playpaus.png \ - Skins/Classic/pledit.png \ - Skins/Classic/pledit.txt \ - Skins/Classic/posbar.png \ - Skins/Classic/shufrep.png \ - Skins/Classic/skin-classic.hints \ - Skins/Classic/skin.hints \ - Skins/Classic/text.png \ - Skins/Classic/titlebar.png \ - Skins/Classic/viscolor.txt \ - Skins/Classic/volume.png \ - Skins/Classic1.3/balance.png \ - Skins/Classic1.3/cbuttons.png \ - Skins/Classic1.3/eq_ex.png \ - Skins/Classic1.3/eqmain.png \ - Skins/Classic1.3/main.png \ - Skins/Classic1.3/monoster.png \ - Skins/Classic1.3/nums_ex.png \ - Skins/Classic1.3/playpaus.png \ - Skins/Classic1.3/pledit.png \ - Skins/Classic1.3/pledit.txt \ - Skins/Classic1.3/posbar.png \ - Skins/Classic1.3/shufrep.png \ - Skins/Classic1.3/skin-classic.hints \ - Skins/Classic1.3/skin.hints \ - Skins/Classic1.3/text.png \ - Skins/Classic1.3/titlebar.png \ - Skins/Classic1.3/viscolor.txt \ - Skins/Classic1.3/volume.png \ - Skins/Default/cbuttons.png \ - Skins/Default/eq_ex.png \ - Skins/Default/eqmain.png \ - Skins/Default/main.png \ - Skins/Default/monoster.png \ - Skins/Default/nums_ex.png \ - Skins/Default/playpaus.png \ - Skins/Default/pledit.png \ - Skins/Default/pledit.txt \ - Skins/Default/posbar.png \ - Skins/Default/shufrep.png \ - Skins/Default/skin.hints \ - Skins/Default/text.png \ - Skins/Default/titlebar.png \ - Skins/Default/viscolor.txt \ - Skins/Default/volume.png \ - Skins/Ivory/balance.png \ - Skins/Ivory/cbuttons.png \ - Skins/Ivory/eq_ex.png \ - Skins/Ivory/eqmain.png \ - Skins/Ivory/main.png \ - Skins/Ivory/monoster.png \ - Skins/Ivory/nums_ex.png \ - Skins/Ivory/playpaus.png \ - Skins/Ivory/pledit.png \ - Skins/Ivory/pledit.txt \ - Skins/Ivory/posbar.png \ - Skins/Ivory/shufrep.png \ - Skins/Ivory/skin.hints \ - Skins/Ivory/text.png \ - Skins/Ivory/titlebar.png \ - Skins/Ivory/viscolor.txt \ - Skins/Ivory/volume.png \ - Skins/Osmosis/balance.png \ - Skins/Osmosis/cbuttons.png \ - Skins/Osmosis/eq_ex.png \ - Skins/Osmosis/eqmain.png \ - Skins/Osmosis/main.png \ - Skins/Osmosis/monoster.png \ - Skins/Osmosis/nums_ex.png \ - Skins/Osmosis/playpaus.png \ - Skins/Osmosis/pledit.png \ - Skins/Osmosis/pledit.txt \ - Skins/Osmosis/posbar.png \ - Skins/Osmosis/shufrep.png \ - Skins/Osmosis/skin.hints \ - Skins/Osmosis/text.png \ - Skins/Osmosis/titlebar.png \ - Skins/Osmosis/viscolor.txt \ - Skins/Osmosis/volume.png \ - Skins/TinyPlayer/balance.png \ - Skins/TinyPlayer/cbuttons.png \ - Skins/TinyPlayer/eq_ex.png \ - Skins/TinyPlayer/eqmain.png \ - Skins/TinyPlayer/main.png \ - Skins/TinyPlayer/monoster.png \ - Skins/TinyPlayer/nums_ex.png \ - Skins/TinyPlayer/playpaus.png \ - Skins/TinyPlayer/pledit.png \ - Skins/TinyPlayer/pledit.txt \ - Skins/TinyPlayer/posbar.png \ - Skins/TinyPlayer/shufrep.png \ - Skins/TinyPlayer/skin.hints \ - Skins/TinyPlayer/text.png \ - Skins/TinyPlayer/titlebar.png \ - Skins/TinyPlayer/viscolor.txt \ - Skins/TinyPlayer/volume.png \ - Skins/Refugee/cbuttons.png \ - Skins/Refugee/eq_ex.png \ - Skins/Refugee/eqmain.png \ - Skins/Refugee/main.png \ - Skins/Refugee/monoster.png \ - Skins/Refugee/nums_ex.png \ - Skins/Refugee/playpaus.png \ - Skins/Refugee/pledit.png \ - Skins/Refugee/pledit.txt \ - Skins/Refugee/posbar.png \ - Skins/Refugee/shufrep.png \ - Skins/Refugee/skin.hints \ - Skins/Refugee/text.png \ - Skins/Refugee/titlebar.png \ - Skins/Refugee/viscolor.txt \ - Skins/Refugee/volume.png - plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR} LD = ${CXX} diff --git a/src/skins/actions-mainwin.h b/src/skins/actions-mainwin.h index cad103b..a534696 100644 --- a/src/skins/actions-mainwin.h +++ b/src/skins/actions-mainwin.h @@ -20,11 +20,11 @@ #ifndef SKINS_ACTIONS_MAINWIN_H #define SKINS_ACTIONS_MAINWIN_H -void action_ab_clear(void); -void action_ab_set(void); -void action_play_file(void); -void action_play_location(void); -void action_playlist_manager(void); -void action_search_tool(void); +void action_ab_clear (); +void action_ab_set (); +void action_play_file (); +void action_play_location (); +void action_playlist_manager (); +void action_search_tool (); #endif /* SKINS_ACTIONS_MAINWIN_H */ diff --git a/src/skins/actions-playlist.h b/src/skins/actions-playlist.h index 2afd481..97b04ea 100644 --- a/src/skins/actions-playlist.h +++ b/src/skins/actions-playlist.h @@ -20,64 +20,63 @@ #ifndef SKINS_ACTIONS_PLAYLIST_H #define SKINS_ACTIONS_PLAYLIST_H -void action_playlist_refresh_list(void); +void action_playlist_refresh_list (); -void action_playlist_play(void); -void action_playlist_new(void); -void action_playlist_prev(void); -void action_playlist_next(void); -void action_playlist_rename(void); -void action_playlist_delete(void); +void action_playlist_play (); +void action_playlist_prev (); +void action_playlist_next (); +void action_playlist_rename (); +void action_playlist_delete (); -void action_playlist_search_and_select(void); -void action_playlist_invert_selection(void); -void action_playlist_select_all(void); -void action_playlist_select_none(void); +void action_playlist_search_and_select (); +void action_playlist_invert_selection (); +void action_playlist_select_all (); +void action_playlist_select_none (); -void action_playlist_clear_queue(void); -void action_playlist_remove_unavailable(void); -void action_playlist_remove_dupes_by_title(void); -void action_playlist_remove_dupes_by_filename(void); -void action_playlist_remove_dupes_by_full_path(void); -void action_playlist_remove_all(void); -void action_playlist_remove_selected(void); -void action_playlist_remove_unselected(void); +void action_playlist_clear_queue (); +void action_playlist_remove_unavailable (); +void action_playlist_remove_dupes_by_title (); +void action_playlist_remove_dupes_by_filename (); +void action_playlist_remove_dupes_by_full_path (); +void action_playlist_remove_all (); +void action_playlist_remove_selected (); +void action_playlist_remove_unselected (); -void action_playlist_copy (void); -void action_playlist_cut (void); -void action_playlist_paste (void); +void action_playlist_copy (); +void action_playlist_cut (); +void action_playlist_paste (); -void action_playlist_add_url(void); -void action_playlist_add_files(void); +void action_playlist_add_url (); +void action_playlist_add_files (); -void action_playlist_randomize_list(void); -void action_playlist_reverse_list(void); +void action_playlist_randomize_list (); +void action_playlist_reverse_list (); -void action_playlist_sort_by_title(void); -void action_playlist_sort_by_album(void); -void action_playlist_sort_by_artist(void); -void action_playlist_sort_by_album_artist(void); -void action_playlist_sort_by_length(void); -void action_playlist_sort_by_genre(void); -void action_playlist_sort_by_filename(void); -void action_playlist_sort_by_full_path(void); -void action_playlist_sort_by_date(void); -void action_playlist_sort_by_track_number(void); -void action_playlist_sort_by_custom_title(void); +void action_playlist_sort_by_title (); +void action_playlist_sort_by_album (); +void action_playlist_sort_by_artist (); +void action_playlist_sort_by_album_artist (); +void action_playlist_sort_by_length (); +void action_playlist_sort_by_genre (); +void action_playlist_sort_by_filename (); +void action_playlist_sort_by_full_path (); +void action_playlist_sort_by_date (); +void action_playlist_sort_by_track_number (); +void action_playlist_sort_by_custom_title (); -void action_playlist_sort_selected_by_title(void); -void action_playlist_sort_selected_by_album(void); -void action_playlist_sort_selected_by_artist(void); -void action_playlist_sort_selected_by_album_artist(void); -void action_playlist_sort_selected_by_length(void); -void action_playlist_sort_selected_by_genre(void); -void action_playlist_sort_selected_by_filename(void); -void action_playlist_sort_selected_by_full_path(void); -void action_playlist_sort_selected_by_date(void); -void action_playlist_sort_selected_by_track_number(void); -void action_playlist_sort_selected_by_custom_title(void); +void action_playlist_sort_selected_by_title (); +void action_playlist_sort_selected_by_album (); +void action_playlist_sort_selected_by_artist (); +void action_playlist_sort_selected_by_album_artist (); +void action_playlist_sort_selected_by_length (); +void action_playlist_sort_selected_by_genre (); +void action_playlist_sort_selected_by_filename (); +void action_playlist_sort_selected_by_full_path (); +void action_playlist_sort_selected_by_date (); +void action_playlist_sort_selected_by_track_number (); +void action_playlist_sort_selected_by_custom_title (); -void action_playlist_track_info(void); -void action_queue_toggle(void); +void action_playlist_track_info (); +void action_queue_toggle (); #endif /* SKINS_ACTIONS_PLAYLIST_H */ diff --git a/src/skins/actions.cc b/src/skins/actions.cc new file mode 100644 index 0000000..3d42dcb --- /dev/null +++ b/src/skins/actions.cc @@ -0,0 +1,282 @@ +/* Audacious - Cross-platform multimedia player + * Copyright (C) 2005-2011 Audacious development team. + * + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include "actions-mainwin.h" +#include "actions-playlist.h" +#include "main.h" +#include "plugin-window.h" + +#include <gtk/gtk.h> + +#include <libaudcore/drct.h> +#include <libaudcore/i18n.h> +#include <libaudcore/playlist.h> +#include <libaudcore/plugins.h> +#include <libaudgui/libaudgui.h> + +#define ACTIVE (aud_playlist_get_active ()) + +void action_ab_clear () +{ + mainwin_show_status_message (_("Repeat points cleared.")); + aud_drct_set_ab_repeat (-1, -1); +} + +void action_ab_set () +{ + if (aud_drct_get_length () > 0) + { + int a, b; + aud_drct_get_ab_repeat (a, b); + + if (a < 0 || b >= 0) + { + a = aud_drct_get_time (); + b = -1; + mainwin_show_status_message (_("Repeat point A set.")); + } + else + { + b = aud_drct_get_time (); + mainwin_show_status_message (_("Repeat point B set.")); + } + + aud_drct_set_ab_repeat (a, b); + } +} + +void action_play_file () + { audgui_run_filebrowser (true); } +void action_play_location () + { audgui_show_add_url_window (true); } + +void action_playlist_manager () +{ + PluginHandle * manager = aud_plugin_lookup_basename ("playlist-manager"); + if (manager) + { + aud_plugin_enable (manager, true); + focus_plugin_window (manager); + } +} + +void action_search_tool () +{ + PluginHandle * search = aud_plugin_lookup_basename ("search-tool"); + if (search) + { + aud_plugin_enable (search, true); + focus_plugin_window (search); + } +} + +void action_playlist_refresh_list () + { aud_playlist_rescan (ACTIVE); } +void action_playlist_play () + { aud_playlist_play (ACTIVE); } + +void action_playlist_prev () +{ + int playlist = ACTIVE; + if (playlist > 0) + aud_playlist_set_active (playlist - 1); + else + { + int count = aud_playlist_count (); + if (count > 1) + aud_playlist_set_active (count - 1); + } +} + +void action_playlist_next () +{ + int playlist = ACTIVE; + int count = aud_playlist_count (); + if (playlist + 1 < count) + aud_playlist_set_active (playlist + 1); + else if (count > 1) + aud_playlist_set_active (0); +} + +void action_playlist_rename () + { audgui_show_playlist_rename (ACTIVE); } +void action_playlist_delete () + { audgui_confirm_playlist_delete (ACTIVE); } + +void action_playlist_invert_selection () +{ + int playlist = ACTIVE; + int entries = aud_playlist_entry_count (playlist); + for (int entry = 0; entry < entries; entry ++) + aud_playlist_entry_set_selected (playlist, entry, + ! aud_playlist_entry_get_selected (playlist, entry)); +} + +void action_playlist_select_all () + { aud_playlist_select_all (ACTIVE, true); } +void action_playlist_select_none () + { aud_playlist_select_all (ACTIVE, false); } + +void action_playlist_clear_queue () +{ + int playlist = ACTIVE; + aud_playlist_queue_delete (playlist, 0, aud_playlist_queue_count (playlist)); +} + +void action_playlist_remove_unavailable () + { aud_playlist_remove_failed (ACTIVE); } +void action_playlist_remove_dupes_by_title () + { aud_playlist_remove_duplicates_by_scheme (ACTIVE, Playlist::Title); } +void action_playlist_remove_dupes_by_filename () + { aud_playlist_remove_duplicates_by_scheme (ACTIVE, Playlist::Filename); } +void action_playlist_remove_dupes_by_full_path () + { aud_playlist_remove_duplicates_by_scheme (ACTIVE, Playlist::Path); } + +void action_playlist_remove_all () +{ + int playlist = ACTIVE; + aud_playlist_entry_delete (playlist, 0, aud_playlist_entry_count (playlist)); +} + +void action_playlist_remove_selected () + { aud_playlist_delete_selected (ACTIVE); } + +void action_playlist_remove_unselected () +{ + action_playlist_invert_selection (); + action_playlist_remove_selected (); + action_playlist_select_all (); +} + +void action_playlist_copy () +{ + GtkClipboard * clip = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); + Index<char> list = audgui_urilist_create_from_selected (ACTIVE); + + if (list.len ()) + gtk_clipboard_set_text (clip, list.begin (), list.len ()); +} + +void action_playlist_cut () +{ + action_playlist_copy (); + action_playlist_remove_selected (); +} + +void action_playlist_paste () +{ + GtkClipboard * clip = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); + char * list = gtk_clipboard_wait_for_text (clip); + + if (list) + { + int playlist = ACTIVE; + audgui_urilist_insert (playlist, aud_playlist_get_focus (playlist), list); + g_free (list); + } +} + +void action_playlist_add_url () + { audgui_show_add_url_window (false); } +void action_playlist_add_files () + { audgui_run_filebrowser (false); } + +void action_playlist_randomize_list () + { aud_playlist_randomize (ACTIVE); } +void action_playlist_reverse_list () + { aud_playlist_reverse (ACTIVE); } + +void action_playlist_sort_by_title () + { aud_playlist_sort_by_scheme (ACTIVE, Playlist::Title); } +void action_playlist_sort_by_album () + { aud_playlist_sort_by_scheme (ACTIVE, Playlist::Album); } +void action_playlist_sort_by_artist () + { aud_playlist_sort_by_scheme (ACTIVE, Playlist::Artist); } +void action_playlist_sort_by_album_artist () + { aud_playlist_sort_by_scheme (ACTIVE, Playlist::AlbumArtist); } +void action_playlist_sort_by_length () + { aud_playlist_sort_by_scheme (ACTIVE, Playlist::Length); } +void action_playlist_sort_by_genre () + { aud_playlist_sort_by_scheme (ACTIVE, Playlist::Genre); } +void action_playlist_sort_by_filename () + { aud_playlist_sort_by_scheme (ACTIVE, Playlist::Filename); } +void action_playlist_sort_by_full_path () + { aud_playlist_sort_by_scheme (ACTIVE, Playlist::Path); } +void action_playlist_sort_by_date () + { aud_playlist_sort_by_scheme (ACTIVE, Playlist::Date); } +void action_playlist_sort_by_track_number () + { aud_playlist_sort_by_scheme (ACTIVE, Playlist::Track); } +void action_playlist_sort_by_custom_title () + { aud_playlist_sort_by_scheme (ACTIVE, Playlist::FormattedTitle); } + +void action_playlist_sort_selected_by_title () + { aud_playlist_sort_selected_by_scheme (ACTIVE, Playlist::Title); } +void action_playlist_sort_selected_by_album () + { aud_playlist_sort_selected_by_scheme (ACTIVE, Playlist::Album); } +void action_playlist_sort_selected_by_artist () + { aud_playlist_sort_selected_by_scheme (ACTIVE, Playlist::Artist); } +void action_playlist_sort_selected_by_album_artist () + { aud_playlist_sort_selected_by_scheme (ACTIVE, Playlist::AlbumArtist); } +void action_playlist_sort_selected_by_length () + { aud_playlist_sort_selected_by_scheme (ACTIVE, Playlist::Length); } +void action_playlist_sort_selected_by_genre () + { aud_playlist_sort_selected_by_scheme (ACTIVE, Playlist::Genre); } +void action_playlist_sort_selected_by_filename () + { aud_playlist_sort_selected_by_scheme (ACTIVE, Playlist::Filename); } +void action_playlist_sort_selected_by_full_path () + { aud_playlist_sort_selected_by_scheme (ACTIVE, Playlist::Path); } +void action_playlist_sort_selected_by_date () + { aud_playlist_sort_selected_by_scheme (ACTIVE, Playlist::Date); } +void action_playlist_sort_selected_by_track_number () + { aud_playlist_sort_selected_by_scheme (ACTIVE, Playlist::Track); } +void action_playlist_sort_selected_by_custom_title () + { aud_playlist_sort_selected_by_scheme (ACTIVE, Playlist::FormattedTitle); } + +void action_playlist_track_info () +{ + int playlist = ACTIVE; + audgui_infowin_show (playlist, aud_playlist_get_focus (playlist)); +} + +void action_queue_toggle () +{ + int playlist = ACTIVE; + int focus = aud_playlist_get_focus (playlist); + if (focus == -1) + return; + + /* make sure focused row is selected */ + if (! aud_playlist_entry_get_selected (playlist, focus)) + { + aud_playlist_select_all (playlist, false); + aud_playlist_entry_set_selected (playlist, focus, true); + } + + int at = aud_playlist_queue_find_entry (playlist, focus); + if (at == -1) + aud_playlist_queue_insert_selected (playlist, -1); + else + aud_playlist_queue_delete_selected (playlist); +} diff --git a/src/skins/button.cc b/src/skins/button.cc new file mode 100644 index 0000000..419ae6d --- /dev/null +++ b/src/skins/button.cc @@ -0,0 +1,132 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2011 John Lindgren + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include "skins_cfg.h" +#include "button.h" + +void Button::draw (cairo_t * cr) +{ + switch (m_type) + { + case Normal: + if (m_pressed) + skin_draw_pixbuf (cr, m_si2, m_px, m_py, 0, 0, m_w, m_h); + else + skin_draw_pixbuf (cr, m_si1, m_nx, m_ny, 0, 0, m_w, m_h); + break; + case Toggle: + if (m_active) + { + if (m_pressed) + skin_draw_pixbuf (cr, m_si2, m_ppx, m_ppy, 0, 0, m_w, m_h); + else + skin_draw_pixbuf (cr, m_si1, m_pnx, m_pny, 0, 0, m_w, m_h); + } + else + { + if (m_pressed) + skin_draw_pixbuf (cr, m_si2, m_px, m_py, 0, 0, m_w, m_h); + else + skin_draw_pixbuf (cr, m_si1, m_nx, m_ny, 0, 0, m_w, m_h); + } + break; + case Small: + break; + } +} + +bool Button::button_press (GdkEventButton * event) +{ + /* pass events through to the parent widget only if neither the press nor + * release signals are connected; sending one and not the other causes + * problems (in particular with dragging windows around) */ + if (event->button == 1 && (press || release)) + { + m_pressed = true; + if (press) + press (this, event); + } + else if (event->button == 3 && (rpress || rrelease)) + { + m_rpressed = true; + if (rpress) + rpress (this, event); + } + else + return false; + + if (m_type != Small) + queue_draw (); + + return true; +} + +bool Button::button_release (GdkEventButton * event) +{ + if (event->button == 1 && (press || release)) + { + if (! m_pressed) + return true; + + m_pressed = false; + if (m_type == Toggle) + m_active = ! m_active; + if (release) + release (this, event); + } + else if (event->button == 3 && (rpress || rrelease)) + { + if (! m_rpressed) + return true; + + m_rpressed = false; + if (rrelease) + rrelease (this, event); + } + else + return false; + + if (m_type != Small) + queue_draw (); + + return true; +} + +Button::Button (Type type, int w, int h, int nx, int ny, int px, int py, + int pnx, int pny, int ppx, int ppy, SkinPixmapId si1, SkinPixmapId si2) : + m_type (type), + m_w (w), m_h (h), + m_nx (nx), m_ny (ny), m_px (px), m_py (py), + m_pnx (pnx), m_pny (pny), m_ppx (ppx), m_ppy (ppy), + m_si1 (si1), m_si2 (si2) +{ + set_scale (config.scale); + add_input (w, h, false, type != Small); +} + +void Button::set_active (bool active) +{ + if (m_active != active) + { + m_active = active; + queue_draw (); + } +} diff --git a/src/skins/button.h b/src/skins/button.h new file mode 100644 index 0000000..16941ab --- /dev/null +++ b/src/skins/button.h @@ -0,0 +1,78 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2011 John Lindgren + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#ifndef SKINS_UI_SKINNED_BUTTON_H +#define SKINS_UI_SKINNED_BUTTON_H + +#include "widget.h" +#include "skin.h" + +class Button; + +typedef void (* ButtonCB) (Button * button, GdkEventButton * event); + +class Button : public Widget +{ +public: + // transparent button + Button (int w, int h) : + Button (Small, w, h, 0, 0, 0, 0, 0, 0, 0, 0, SKIN_MAIN, SKIN_MAIN) {} + + // basic skinned button + Button (int w, int h, int nx, int ny, int px, int py, SkinPixmapId si1, SkinPixmapId si2) : + Button (Normal, w, h, nx, ny, px, py, 0, 0, 0, 0, si1, si2) {} + + // skinned toggle button + Button (int w, int h, int nx, int ny, int px, int py, int pnx, int pny, + int ppx, int ppy, SkinPixmapId si1, SkinPixmapId si2) : + Button (Toggle, w, h, nx, ny, px, py, pnx, pny, ppx, ppy, si1, si2) {} + + void on_press (ButtonCB callback) { press = callback; } + void on_release (ButtonCB callback) { release = callback; } + void on_rpress (ButtonCB callback) { rpress = callback; } + void on_rrelease (ButtonCB callback) { rrelease = callback; } + + bool get_active () { return m_active; } + void set_active (bool active); + +private: + enum Type {Normal, Toggle, Small}; + + Button (Type type, int w, int h, int nx, int ny, int px, int py, int pnx, + int pny, int ppx, int ppy, SkinPixmapId si1, SkinPixmapId si2); + + void draw (cairo_t * cr); + bool button_press (GdkEventButton * event); + bool button_release (GdkEventButton * event); + + Type m_type; + int m_w, m_h; + int m_nx, m_ny, m_px, m_py; + int m_pnx, m_pny, m_ppx, m_ppy; + SkinPixmapId m_si1, m_si2; + + bool m_pressed = false, m_rpressed = false, m_active = false; + + ButtonCB press = nullptr, release = nullptr; + ButtonCB rpress = nullptr, rrelease = nullptr; +}; + +#endif diff --git a/src/skins/dock.cc b/src/skins/dock.cc new file mode 100644 index 0000000..1fd7f0d --- /dev/null +++ b/src/skins/dock.cc @@ -0,0 +1,356 @@ +/* + * ui_dock.c + * Copyright 2011 John Lindgren + * + * This file is part of Audacious. + * + * Audacious 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, version 2 or version 3 of the License. + * + * Audacious 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 + * Audacious. If not, see <http://www.gnu.org/licenses/>. + * + * The Audacious team does not consider modular code linking to Audacious or + * using our public API to be a derived work. + */ + +/* + * Rough outline + * ============= + * + * When moving a window: + * 1. If this is the main window, find (recursively) the windows docked to it. + * 2. Adjust the offsets to snap to another window (not docked) or a screen edge. + * 3. Move the docked windows by the same offsets. + * + * When resizing a window: + * 1. Find (recursively) the windows docked to the bottom edge of this one. + * If we are making the window shorter, exclude windows that are docked to + * the bottom of another window (not docked) to avoid overlap. + * 2. Move the docked windows by the difference in window height. + * 3. Repeat the process for windows docked to the right edge of this one. + */ + +#include <stdlib.h> + +#include "window.h" + +#define SNAP_DISTANCE 10 + +enum { + DOCK_TYPE_LEFT = 1 << 0, + DOCK_TYPE_RIGHT = 1 << 1, + DOCK_TYPE_TOP = 1 << 2, + DOCK_TYPE_BOTTOM = 1 << 3 +}; + +#define DOCK_TYPE_ANY (DOCK_TYPE_LEFT | DOCK_TYPE_RIGHT | DOCK_TYPE_TOP | DOCK_TYPE_BOTTOM) + +typedef struct { + Window * window; + int * x, * y; + int w, h; + bool docked; +} DockWindow; + +static DockWindow windows[N_WINDOWS]; +static int last_x, last_y; + +static inline int least_abs (int a, int b) +{ + return (abs (a) < abs (b)) ? a : b; +} + +void dock_add_window (int id, Window * window, int * x, int * y, int w, int h) +{ + DockWindow & dw = windows[id]; + + dw.window = window; + dw.x = x; + dw.y = y; + dw.w = w; + dw.h = h; +} + +void dock_remove_window (int id) +{ + windows[id].window = nullptr; +} + +static void dock_sync () +{ + for (DockWindow & dw : windows) + { + if (dw.window) + dw.window->getPosition (dw.x, dw.y); + } +} + +static void clear_docked () +{ + for (DockWindow & dw : windows) + dw.docked = false; +} + +static bool is_docked (DockWindow & dw, DockWindow & base, int type) +{ + return ((type & DOCK_TYPE_LEFT) && * dw.x + dw.w == * base.x) || + ((type & DOCK_TYPE_RIGHT) && * dw.x == * base.x + base.w) || + ((type & DOCK_TYPE_TOP) && * dw.y + dw.h == * base.y) || + ((type & DOCK_TYPE_BOTTOM) && * dw.y == * base.y + base.h); +} + +static void find_docked (DockWindow & base, int type) +{ + for (DockWindow & dw : windows) + { + if (dw.docked || & dw == & base) + continue; + + dw.docked = is_docked (dw, base, type); + if (dw.docked) + find_docked (dw, type); + } +} + +static void invert_docked () +{ + for (DockWindow & dw : windows) + dw.docked = ! dw.docked; +} + +void dock_set_size (int id, int w, int h) +{ + DockWindow & base = windows[id]; + + dock_sync (); + + if (h != base.h) + { + /* 1. Find the windows docked below this one. */ + + clear_docked (); + find_docked (base, DOCK_TYPE_BOTTOM); + + if (h < base.h) + { + /* 2. This part is tricky. By flipping the docked flag on all the + windows, we consider the windows not docked to this one as a + docked group. We then add (recursively) any other windows + docked to these ones (i.e. the windows docked to these *and* + to the one being shortened). The one being shortened must be + excluded from the search. Since at this point it is marked as + docked, it is excluded automatically. Finally, flipping the + docked flag back again leaves us with only the windows docked + to the one being shortened and not to any others. */ + + invert_docked (); + + for (DockWindow & dw : windows) + { + if (! dw.docked || & dw == & base) + continue; + + find_docked (dw, DOCK_TYPE_BOTTOM); + } + + invert_docked (); + } + + /* 3. Move the docked windows by the difference in height. */ + + for (DockWindow & dw : windows) + { + if (! dw.docked) + continue; + + * dw.y += h - base.h; + if (dw.window) + dw.window->move (* dw.x, * dw.y); + } + } + + if (w != base.w) + { + /* 4. Repeat the process for the windows docked to the right. */ + + clear_docked (); + find_docked (base, DOCK_TYPE_RIGHT); + + if (w < base.w) + { + invert_docked (); + + for (DockWindow & dw : windows) + { + if (! dw.docked || & dw == & base) + continue; + + find_docked (dw, DOCK_TYPE_RIGHT); + } + + invert_docked (); + } + + for (DockWindow & dw : windows) + { + if (! dw.docked) + continue; + + * dw.x += w - base.w; + if (dw.window) + dw.window->move (* dw.x, * dw.y); + } + } + + /* 5. Set the window size. (The actual resize is done by the caller.) */ + + base.w = w; + base.h = h; +} + +void dock_move_start (int id, int x, int y) +{ + DockWindow & dw = windows[id]; + + dock_sync (); + + last_x = x; + last_y = y; + + /* 1. If this is the main window, find the windows docked to it. */ + + clear_docked (); + dw.docked = true; + if (id == WINDOW_MAIN) + find_docked (dw, DOCK_TYPE_ANY); +} + +void dock_move (int x, int y) +{ + int hori, vert; + + if (x == last_x && y == last_y) + return; + + /* 2. Nominally move all the windows in the group the requested distance, + and update the reference point. */ + + hori = x - last_x; + vert = y - last_y; + + for (DockWindow & dw : windows) + { + if (! dw.docked) + continue; + + * dw.x += hori; + * dw.y += vert; + } + + last_x = x; + last_y = y; + + + /* 3. Find the least snap distance we must move so that + (a) a window in the group is touching a screen edge or + (b) a window in the group is touching a window not in the group. */ + + hori = SNAP_DISTANCE + 1; + vert = SNAP_DISTANCE + 1; + + GdkScreen * screen = gdk_screen_get_default (); + int monitors = gdk_screen_get_n_monitors (screen); + + for (int m = 0; m < monitors; m ++) + { + GdkRectangle rect; + gdk_screen_get_monitor_geometry (screen, m, & rect); + + for (DockWindow & dw : windows) + { + if (! dw.docked) + continue; + + /* We only test half the combinations here, as it is not very + helpful to have e.g. the right edge of a window touching the left + edge of a monitor (think about it). */ + + hori = least_abs (hori, rect.x - * dw.x); + hori = least_abs (hori, (rect.x + rect.width) - (* dw.x + dw.w)); + vert = least_abs (vert, rect.y - * dw.y); + vert = least_abs (vert, (rect.y + rect.height) - (* dw.y + dw.h)); + } + } + + for (DockWindow & dw : windows) + { + if (! dw.docked) + continue; + + for (DockWindow & dw2 : windows) + { + if (dw2.docked) + continue; + + hori = least_abs (hori, * dw2.x - * dw.x); + hori = least_abs (hori, * dw2.x - (* dw.x + dw.w)); + hori = least_abs (hori, (* dw2.x + dw2.w) - * dw.x); + hori = least_abs (hori, (* dw2.x + dw2.w) - (* dw.x + dw.w)); + vert = least_abs (vert, * dw2.y - * dw.y); + vert = least_abs (vert, * dw2.y - (* dw.y + dw.h)); + vert = least_abs (vert, (* dw2.y + dw2.h) - * dw.y); + vert = least_abs (vert, (* dw2.y + dw2.h) - (* dw.y + dw.h)); + } + } + + /* 4. If the snap distances are within range, nominally move all the windows + in the group, and update the reference point again. */ + + if (abs (hori) > SNAP_DISTANCE) + hori = 0; + if (abs (vert) > SNAP_DISTANCE) + vert = 0; + + for (DockWindow & dw : windows) + { + if (! dw.docked) + continue; + + * dw.x += hori; + * dw.y += vert; + } + + last_x += hori; + last_y += vert; + + /* 5. Really move the windows. */ + + for (DockWindow & dw : windows) + { + if (dw.docked && dw.window) + dw.window->move (* dw.x, * dw.y); + } +} + +void dock_change_scale (int old_scale, int new_scale) +{ + DockWindow & main = windows[WINDOW_MAIN]; + + for (DockWindow & dw : windows) + { + dw.w = dw.w * new_scale / old_scale; + dw.h = dw.h * new_scale / old_scale; + + if (& dw != & main) + { + * dw.x = * main.x + (* dw.x - * main.x) * new_scale / old_scale; + * dw.y = * main.y + (* dw.y - * main.y) * new_scale / old_scale; + } + } +} diff --git a/src/skins/drag-handle.cc b/src/skins/drag-handle.cc index 9f08895..2aac674 100644 --- a/src/skins/drag-handle.cc +++ b/src/skins/drag-handle.cc @@ -22,85 +22,45 @@ #include "drag-handle.h" #include "skins_cfg.h" -typedef struct { - gboolean held; - int x_origin, y_origin; - void (* press) (void); - void (* drag) (int x_offset, int y_offset); -} DHandleData; - -static gboolean handle_button_press (GtkWidget * handle, GdkEventButton * event) +bool DragHandle::button_press (GdkEventButton * event) { - DHandleData * data = (DHandleData *) g_object_get_data ((GObject *) handle, "dhandledata"); - g_return_val_if_fail (data, FALSE); - if (event->button != 1) - return FALSE; + return false; - data->held = TRUE; - data->x_origin = event->x_root; - data->y_origin = event->y_root; + m_held = true; + m_x_origin = event->x_root; + m_y_origin = event->y_root; - if (data->press) - data->press (); + if (press) + press (); - return TRUE; + return true; } -static gboolean handle_button_release (GtkWidget * handle, GdkEventButton * - event) +bool DragHandle::button_release (GdkEventButton * event) { - DHandleData * data = (DHandleData *) g_object_get_data ((GObject *) handle, "dhandledata"); - g_return_val_if_fail (data, FALSE); - if (event->button != 1) - return FALSE; + return false; - data->held = FALSE; - return TRUE; + m_held = false; + return true; } -static gboolean handle_motion (GtkWidget * handle, GdkEventMotion * event) +bool DragHandle::motion (GdkEventMotion * event) { - DHandleData * data = (DHandleData *) g_object_get_data ((GObject *) handle, "dhandledata"); - g_return_val_if_fail (data, FALSE); - - if (! data->held) - return TRUE; - - if (data->drag) - data->drag ((event->x_root - data->x_origin) / config.scale, - (event->y_root - data->y_origin) / config.scale); + if (! m_held) + return true; - return TRUE; -} + if (drag) + drag ((event->x_root - m_x_origin) / config.scale, + (event->y_root - m_y_origin) / config.scale); -static void handle_destroy (GtkWidget * handle) -{ - g_free (g_object_get_data ((GObject *) handle, "dhandledata")); + return true; } -GtkWidget * drag_handle_new (int w, int h, void (* press) (void), void - (* drag) (int x, int y)) +DragHandle::DragHandle (int w, int h, void (* press) (), void (* drag) (int x, int y)) : + press (press), drag (drag) { - GtkWidget * handle = gtk_event_box_new (); - gtk_event_box_set_visible_window ((GtkEventBox *) handle, FALSE); - gtk_widget_set_size_request (handle, w * config.scale, h * config.scale); - gtk_widget_add_events (handle, GDK_BUTTON_PRESS_MASK | - GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK); - - g_signal_connect (handle, "button-press-event", (GCallback) - handle_button_press, nullptr); - g_signal_connect (handle, "button-release-event", (GCallback) - handle_button_release, nullptr); - g_signal_connect (handle, "motion-notify-event", (GCallback) handle_motion, - nullptr); - g_signal_connect (handle, "destroy", (GCallback) handle_destroy, nullptr); - - DHandleData * data = g_new0 (DHandleData, 1); - data->press = press; - data->drag = drag; - g_object_set_data ((GObject *) handle, "dhandledata", data); - - return handle; + set_scale (config.scale); + add_input (w, h, true, false); } diff --git a/src/skins/drag-handle.h b/src/skins/drag-handle.h index a8ba6df..c28f928 100644 --- a/src/skins/drag-handle.h +++ b/src/skins/drag-handle.h @@ -22,9 +22,23 @@ #ifndef SKINS_DRAG_HANDLE_H #define SKINS_DRAG_HANDLE_H -#include <gtk/gtk.h> +#include "widget.h" -GtkWidget * drag_handle_new (int w, int h, void (* press) (void), void - (* drag) (int x, int y)); +class DragHandle : public Widget +{ +public: + DragHandle (int w, int h, void (* press) (), void (* drag) (int x, int y)); + +private: + bool button_press (GdkEventButton * event); + bool button_release (GdkEventButton * event); + bool motion (GdkEventMotion * event); + + void (* press) (); + void (* drag) (int x_offset, int y_offset); + + bool m_held = false; + int m_x_origin = 0, m_y_origin = 0; +}; #endif diff --git a/src/skins/draw-compat.h b/src/skins/draw-compat.h deleted file mode 100644 index d17890b..0000000 --- a/src/skins/draw-compat.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * draw-compat.h - * Copyright 2011 John Lindgren - * - * This file is part of Audacious. - * - * Audacious 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, version 2 or version 3 of the License. - * - * Audacious 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 - * Audacious. If not, see <http://www.gnu.org/licenses/>. - * - * The Audacious team does not consider modular code linking to Audacious or - * using our public API to be a derived work. - */ - -#ifndef SKINS_DRAW_COMPAT_H -#define SKINS_DRAW_COMPAT_H - -#include <gtk/gtk.h> - -static void widget_realized (GtkWidget * w) -{ - GdkWindow * window = gtk_widget_get_window (w); - gdk_window_set_back_pixmap (window, nullptr, FALSE); -} - -#define DRAW_SIGNAL "expose-event" -#define DRAW_FUNC_BEGIN(n) static int n (GtkWidget * wid, GdkEventExpose * ev) { \ - cairo_t * cr = gdk_cairo_create (gtk_widget_get_window (wid)); -#define DRAW_FUNC_END cairo_destroy (cr); \ - return TRUE; } - -/* We set None as the background pixmap in order to avoid flickering. Setting - * a blank GtkStyle prevents GTK 2.x from overriding this. */ - -#define DRAW_CONNECT(w,f) do { \ - GtkStyle * style = gtk_style_new (); \ - gtk_widget_set_style (w, style); \ - g_object_unref (style); \ - g_signal_connect (w, "realize", (GCallback) widget_realized, nullptr); \ - g_signal_connect (w, DRAW_SIGNAL, (GCallback) f, nullptr); \ - } while (0); - -#endif diff --git a/src/skins/ui_skinned_equalizer_graph.cc b/src/skins/eq-graph.cc index 42b22d2..e5f0a83 100644 --- a/src/skins/ui_skinned_equalizer_graph.cc +++ b/src/skins/eq-graph.cc @@ -25,21 +25,23 @@ #include <libaudcore/equalizer.h> #include <libaudcore/runtime.h> -#include "draw-compat.h" #include "skins_cfg.h" -#include "ui_skin.h" -#include "ui_skinned_equalizer_graph.h" +#include "skin.h" +#include "eq-graph.h" -static void init_spline (const double * x, const double * y, int n, double * y2) -{ - int i, k; - double p, qn, sig, un, *u; +#define N 10 +static_assert (N == AUD_EQ_NBANDS, "only a 10-band EQ is supported"); - u = (double *) g_malloc(n * sizeof(double)); +static void init_spline (const double * x, const double * y, double * y2) +{ + int k; + double p, qn, sig, un; + double u[N]; y2[0] = u[0] = 0.0; - for (i = 1; i < n - 1; i++) { + for (int i = 1; i < N - 1; i ++) + { sig = ((double) x[i] - x[i - 1]) / ((double) x[i + 1] - x[i - 1]); p = sig * y2[i - 1] + 2.0; y2[i] = (sig - 1.0) / p; @@ -50,21 +52,20 @@ static void init_spline (const double * x, const double * y, int n, double * y2) } qn = un = 0.0; - y2[n - 1] = (un - qn * u[n - 2]) / (qn * y2[n - 2] + 1.0); - for (k = n - 2; k >= 0; k--) + y2[N - 1] = (un - qn * u[N - 2]) / (qn * y2[N - 2] + 1.0); + for (k = N - 2; k >= 0; k --) y2[k] = y2[k] * y2[k + 1] + u[k]; - g_free(u); } -double eval_spline (const double * xa, const double * ya, const double * y2a, - int n, double x) +static double eval_spline (const double * xa, const double * ya, const double * y2a, double x) { int klo, khi, k; double h, b, a; klo = 0; - khi = n - 1; - while (khi - klo > 1) { + khi = N - 1; + while (khi - klo > 1) + { k = (khi + klo) >> 1; if (xa[k] > x) khi = k; @@ -79,29 +80,27 @@ double eval_spline (const double * xa, const double * ya, const double * y2a, (b * b * b - b) * y2a[khi]) * (h * h) / 6.0); } -DRAW_FUNC_BEGIN (eq_graph_draw) - static const double x[10] = {0, 11, 23, 35, 47, 59, 71, 83, 97, 109}; +void EqGraph::draw (cairo_t * cr) +{ + static const double x[N] = {0, 11, 23, 35, 47, 59, 71, 83, 97, 109}; + + if (cairo_image_surface_get_height (skin.pixmaps[SKIN_EQMAIN].get ()) < 313) + return; skin_draw_pixbuf (cr, SKIN_EQMAIN, 0, 294, 0, 0, 113, 19); skin_draw_pixbuf (cr, SKIN_EQMAIN, 0, 314, 0, 9 + (aud_get_double (nullptr, "equalizer_preamp") * 9 + AUD_EQ_MAX_GAIN / 2) / AUD_EQ_MAX_GAIN, 113, 1); - cairo_scale (cr, config.scale, config.scale); - - uint32_t cols[19]; - skin_get_eq_spline_colors(active_skin, cols); - - double bands[AUD_EQ_NBANDS]; + double bands[N]; aud_eq_get_bands (bands); - double yf[10]; - init_spline (x, bands, 10, yf); + double yf[N]; + init_spline (x, bands, yf); - /* now draw a pixelated line with vector graphics ... -- jlindgren */ int py = 0; for (int i = 0; i < 109; i ++) { - int y = 9.5 - eval_spline (x, bands, yf, 10, i) * 9 / AUD_EQ_MAX_GAIN; + int y = 9.5 - eval_spline (x, bands, yf, i) * 9 / AUD_EQ_MAX_GAIN; y = aud::clamp (y, 0, 18); if (!i) @@ -124,24 +123,17 @@ DRAW_FUNC_BEGIN (eq_graph_draw) py = y; - for (y = ymin; y <= ymax; y++) + for (y = ymin; y <= ymax; y ++) { cairo_rectangle (cr, i + 2, y, 1, 1); - set_cairo_color (cr, cols[y]); + set_cairo_color (cr, skin.eq_spline_colors[y]); cairo_fill (cr); } } -DRAW_FUNC_END - -GtkWidget * eq_graph_new (void) -{ - GtkWidget * graph = gtk_drawing_area_new (); - gtk_widget_set_size_request (graph, 113 * config.scale, 19 * config.scale); - DRAW_CONNECT (graph, eq_graph_draw); - return graph; } -void eq_graph_update (GtkWidget * graph) +EqGraph::EqGraph () { - gtk_widget_queue_draw (graph); + set_scale (config.scale); + add_drawable (113, 19); } diff --git a/src/skins/ui_skinned_equalizer_graph.h b/src/skins/eq-graph.h index f26f1f0..3385038 100644 --- a/src/skins/ui_skinned_equalizer_graph.h +++ b/src/skins/eq-graph.h @@ -28,9 +28,16 @@ #ifndef SKINS_UI_SKINNED_EQUALIZER_GRAPH_H #define SKINS_UI_SKINNED_EQUALIZER_GRAPH_H -#include <gtk/gtk.h> +#include "widget.h" -GtkWidget * eq_graph_new (); -void eq_graph_update (GtkWidget * graph); +class EqGraph : public Widget +{ +public: + EqGraph (); + void refresh () { queue_draw (); } + +private: + void draw (cairo_t * cr); +}; #endif diff --git a/src/skins/eq-slider.cc b/src/skins/eq-slider.cc new file mode 100644 index 0000000..507b205 --- /dev/null +++ b/src/skins/eq-slider.cc @@ -0,0 +1,127 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2011 John Lindgren + * + * Based on: + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + */ + +#include <libaudcore/audstrings.h> +#include <libaudcore/equalizer.h> +#include <libaudcore/i18n.h> +#include <libaudcore/runtime.h> + +#include "skins_cfg.h" +#include "main.h" +#include "skin.h" +#include "eq-slider.h" + +void EqSlider::draw (cairo_t * cr) +{ + int frame = 27 - m_pos * 27 / 50; + if (frame < 14) + skin_draw_pixbuf (cr, SKIN_EQMAIN, 13 + 15 * frame, 164, 0, 0, 14, 63); + else + skin_draw_pixbuf (cr, SKIN_EQMAIN, 13 + 15 * (frame - 14), 229, 0, 0, 14, 63); + + if (m_pressed) + skin_draw_pixbuf (cr, SKIN_EQMAIN, 0, 176, 1, m_pos, 11, 11); + else + skin_draw_pixbuf (cr, SKIN_EQMAIN, 0, 164, 1, m_pos, 11, 11); +} + +void EqSlider::moved (int pos) +{ + m_pos = aud::clamp (pos, 0, 50); + if (m_pos == 24 || m_pos == 26) + m_pos = 25; + + m_value = (float) (25 - m_pos) * AUD_EQ_MAX_GAIN / 25; + + if (m_band < 0) + aud_set_double (nullptr, "equalizer_preamp", m_value); + else + aud_eq_set_band (m_band, m_value); + + mainwin_show_status_message (str_printf ("%s: %+.1f dB", (const char *) m_name, m_value)); +} + +bool EqSlider::button_press (GdkEventButton * event) +{ + if (event->button != 1) + return false; + + m_pressed = true; + moved (event->y / config.scale - 5); + queue_draw (); + return true; +} + +bool EqSlider::button_release (GdkEventButton * event) +{ + if (event->button != 1) + return false; + + if (! m_pressed) + return true; + + m_pressed = false; + moved (event->y / config.scale - 5); + queue_draw (); + return true; +} + +bool EqSlider::motion (GdkEventMotion * event) +{ + if (! m_pressed) + return true; + + moved (event->y / config.scale - 5); + queue_draw (); + return true; +} + +bool EqSlider::scroll (GdkEventScroll * event) +{ + if (event->direction == GDK_SCROLL_UP) + moved (m_pos - 2); + else if (event->direction == GDK_SCROLL_DOWN) + moved (m_pos + 2); + + queue_draw (); + return true; +} + +void EqSlider::set_value (float value) +{ + if (m_pressed) + return; + + m_value = value; + m_pos = aud::clamp (25 - (int) (value * 25 / AUD_EQ_MAX_GAIN), 0, 50); + queue_draw (); +} + +EqSlider::EqSlider (const char * name, int band) : + m_name (name), + m_band (band) +{ + set_scale (config.scale); + add_input (14, 63, true, true); +} diff --git a/src/skins/eq-slider.h b/src/skins/eq-slider.h new file mode 100644 index 0000000..c14429f --- /dev/null +++ b/src/skins/eq-slider.h @@ -0,0 +1,55 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2011 John Lindgren + * + * Based on: + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + */ + +#ifndef SKINS_UI_SKINNED_EQUALIZER_SLIDER_H +#define SKINS_UI_SKINNED_EQUALIZER_SLIDER_H + +#include <libaudcore/objects.h> + +#include "widget.h" + +class EqSlider : public Widget +{ +public: + EqSlider (const char * name, int band); + void set_value (float value); + +private: + void draw (cairo_t * cr); + bool button_press (GdkEventButton * event); + bool button_release (GdkEventButton * event); + bool scroll (GdkEventScroll * event); + bool motion (GdkEventMotion * event); + + void moved (int pos); + + String m_name; + int m_band; + + int m_pos = 0; + float m_value = 0; + bool m_pressed = false; +}; + +#endif diff --git a/src/skins/equalizer.cc b/src/skins/equalizer.cc new file mode 100644 index 0000000..9dba3f0 --- /dev/null +++ b/src/skins/equalizer.cc @@ -0,0 +1,289 @@ +/* Audacious - Cross-platform multimedia player + * Copyright (C) 2005-2014 Audacious development team. + * + * Based on BMP: + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include <string.h> +#include <gtk/gtk.h> + +#include <libaudcore/audstrings.h> +#include <libaudcore/drct.h> +#include <libaudcore/equalizer.h> +#include <libaudcore/hook.h> +#include <libaudcore/i18n.h> +#include <libaudcore/runtime.h> +#include <libaudgui/libaudgui.h> +#include <libaudgui/libaudgui-gtk.h> + +#include "menus.h" +#include "plugin.h" +#include "skins_cfg.h" +#include "equalizer.h" +#include "main.h" +#include "button.h" +#include "eq-graph.h" +#include "eq-slider.h" +#include "hslider.h" +#include "window.h" +#include "util.h" +#include "view.h" + +class EqWindow : public Window +{ +public: + EqWindow (bool shaded) : + Window (WINDOW_EQ, & config.equalizer_x, & config.equalizer_y, 275, + shaded ? 14 : 116, shaded) {} + +private: + void draw (cairo_t * cr); + bool button_press (GdkEventButton * event); +}; + +Window * equalizerwin; + +static EqGraph * equalizerwin_graph; +static Button * equalizerwin_on, * equalizerwin_auto; +static Button * equalizerwin_close, * equalizerwin_shade; +static Button * equalizerwin_shaded_close, * equalizerwin_shaded_shade; +static Button * equalizerwin_presets; +static EqSlider * equalizerwin_preamp, * equalizerwin_bands[10]; +static HSlider * equalizerwin_volume, * equalizerwin_balance; + +static void equalizerwin_shade_toggle () +{ + view_set_equalizer_shaded (! aud_get_bool ("skins", "equalizer_shaded")); +} + +static void eq_on_cb (Button * button, GdkEventButton * event) +{ + aud_set_bool (nullptr, "equalizer_active", button->get_active ()); +} + +static void update_from_config (void *, void *) +{ + equalizerwin_on->set_active (aud_get_bool (nullptr, "equalizer_active")); + equalizerwin_preamp->set_value (aud_get_double (nullptr, "equalizer_preamp")); + + double bands[AUD_EQ_NBANDS]; + aud_eq_get_bands (bands); + + for (int i = 0; i < AUD_EQ_NBANDS; i ++) + equalizerwin_bands[i]->set_value (bands[i]); + + equalizerwin_graph->refresh (); +} + +bool EqWindow::button_press (GdkEventButton * event) +{ + if (event->button == 1 && event->type == GDK_2BUTTON_PRESS && + event->window == gtk_widget_get_window (gtk ()) && + event->y < 14 * config.scale) + { + equalizerwin_shade_toggle (); + return true; + } + + if (event->button == 3 && event->type == GDK_BUTTON_PRESS) + { + menu_popup (UI_MENU_MAIN, event->x_root, event->y_root, false, false, + event->button, event->time); + return true; + } + + return Window::button_press (event); +} + +static void equalizerwin_close_cb () +{ + view_set_show_equalizer (false); +} + +static void eqwin_volume_set_knob () +{ + int pos = equalizerwin_volume->get_pos (); + int x = (pos < 32) ? 1 : (pos < 63) ? 4 : 7; + equalizerwin_volume->set_knob (x, 30, x, 30); +} + +void equalizerwin_set_volume_slider (int percent) +{ + equalizerwin_volume->set_pos ((percent * 94 + 50) / 100); + eqwin_volume_set_knob (); +} + +static void eqwin_volume_motion_cb () +{ + eqwin_volume_set_knob (); + int pos = equalizerwin_volume->get_pos (); + int v = (pos * 100 + 47) / 94; + + mainwin_adjust_volume_motion (v); + mainwin_set_volume_slider (v); +} + +static void eqwin_volume_release_cb () +{ + eqwin_volume_set_knob (); + mainwin_adjust_volume_release (); +} + +static void eqwin_balance_set_knob () +{ + int pos = equalizerwin_balance->get_pos (); + int x = (pos < 13) ? 11 : (pos < 26) ? 14 : 17; + equalizerwin_balance->set_knob (x, 30, x, 30); +} + +void equalizerwin_set_balance_slider (int percent) +{ + if (percent > 0) + equalizerwin_balance->set_pos (19 + (percent * 19 + 50) / 100); + else + equalizerwin_balance->set_pos (19 + (percent * 19 - 50) / 100); + + eqwin_balance_set_knob (); +} + +static void eqwin_balance_motion_cb () +{ + eqwin_balance_set_knob (); + int pos = equalizerwin_balance->get_pos (); + pos = aud::min(pos, 38); /* The skin uses a even number of pixels + for the balance-slider *sigh* */ + int b; + if (pos > 19) + b = ((pos - 19) * 100 + 9) / 19; + else + b = ((pos - 19) * 100 - 9) / 19; + + mainwin_adjust_balance_motion (b); + mainwin_set_balance_slider (b); +} + +static void eqwin_balance_release_cb () +{ + eqwin_balance_set_knob (); + mainwin_adjust_balance_release (); +} + +static void equalizerwin_create_widgets () +{ + equalizerwin_on = new Button (25, 12, 10, 119, 128, 119, 69, 119, 187, 119, SKIN_EQMAIN, SKIN_EQMAIN); + equalizerwin->put_widget (false, equalizerwin_on, 14, 18); + equalizerwin_on->set_active (aud_get_bool (nullptr, "equalizer_active")); + equalizerwin_on->on_release (eq_on_cb); + + // AUTO button currently does nothing + equalizerwin_auto = new Button (33, 12, 35, 119, 153, 119, 94, 119, 212, 119, SKIN_EQMAIN, SKIN_EQMAIN); + equalizerwin->put_widget (false, equalizerwin_auto, 39, 18); + + equalizerwin_presets = new Button (44, 12, 224, 164, 224, 176, SKIN_EQMAIN, SKIN_EQMAIN); + equalizerwin->put_widget (false, equalizerwin_presets, 217, 18); + equalizerwin_presets->on_release ((ButtonCB) audgui_show_eq_preset_window); + + equalizerwin_close = new Button (9, 9, 0, 116, 0, 125, SKIN_EQMAIN, SKIN_EQMAIN); + equalizerwin->put_widget (false, equalizerwin_close, 264, 3); + equalizerwin_close->on_release ((ButtonCB) equalizerwin_close_cb); + + equalizerwin_shade = new Button (9, 9, 254, 137, 1, 38, SKIN_EQMAIN, SKIN_EQ_EX); + equalizerwin->put_widget (false, equalizerwin_shade, 254, 3); + equalizerwin_shade->on_release ((ButtonCB) equalizerwin_shade_toggle); + + equalizerwin_shaded_close = new Button (9, 9, 11, 38, 11, 47, SKIN_EQ_EX, SKIN_EQ_EX); + equalizerwin->put_widget (true, equalizerwin_shaded_close, 264, 3); + equalizerwin_shaded_close->on_release ((ButtonCB) equalizerwin_close_cb); + + equalizerwin_shaded_shade = new Button (9, 9, 254, 3, 1, 47, SKIN_EQ_EX, SKIN_EQ_EX); + equalizerwin->put_widget (true, equalizerwin_shaded_shade, 254, 3); + equalizerwin_shaded_shade->on_release ((ButtonCB) equalizerwin_shade_toggle); + + equalizerwin_graph = new EqGraph; + equalizerwin->put_widget (false, equalizerwin_graph, 86, 17); + + equalizerwin_preamp = new EqSlider (_("Preamp"), -1); + equalizerwin->put_widget (false, equalizerwin_preamp, 21, 38); + equalizerwin_preamp->set_value (aud_get_double (nullptr, "equalizer_preamp")); + + const char * const bandnames[AUD_EQ_NBANDS] = {N_("31 Hz"), + N_("63 Hz"), N_("125 Hz"), N_("250 Hz"), N_("500 Hz"), N_("1 kHz"), + N_("2 kHz"), N_("4 kHz"), N_("8 kHz"), N_("16 kHz")}; + double bands[AUD_EQ_NBANDS]; + aud_eq_get_bands (bands); + + for (int i = 0; i < AUD_EQ_NBANDS; i ++) + { + equalizerwin_bands[i] = new EqSlider (_(bandnames[i]), i); + equalizerwin->put_widget (false, equalizerwin_bands[i], 78 + 18 * i, 38); + equalizerwin_bands[i]->set_value (bands[i]); + } + + equalizerwin_volume = new HSlider (0, 94, SKIN_EQ_EX, 97, 8, 61, 4, 3, 7, 1, 30, 1, 30); + equalizerwin->put_widget (true, equalizerwin_volume, 61, 4); + equalizerwin_volume->on_move (eqwin_volume_motion_cb); + equalizerwin_volume->on_release (eqwin_volume_release_cb); + + equalizerwin_balance = new HSlider (0, 39, SKIN_EQ_EX, 42, 8, 164, 4, 3, 7, 11, 30, 11, 30); + equalizerwin->put_widget (true, equalizerwin_balance, 164, 4); + equalizerwin_balance->on_move (eqwin_balance_motion_cb); + equalizerwin_balance->on_release (eqwin_balance_release_cb); +} + +void EqWindow::draw (cairo_t * cr) +{ + skin_draw_pixbuf (cr, SKIN_EQMAIN, 0, 0, 0, 0, 275, is_shaded () ? 14 : 116); + + if (is_shaded ()) + skin_draw_pixbuf (cr, SKIN_EQ_EX, 0, 0, 0, 0, 275, 14); + else + skin_draw_pixbuf (cr, SKIN_EQMAIN, 0, 134, 0, 0, 275, 14); +} + +static void equalizerwin_create_window () +{ + bool shaded = aud_get_bool ("skins", "equalizer_shaded"); + + /* do not allow shading the equalizer if eq_ex.bmp is missing */ + if (! skin.pixmaps[SKIN_EQ_EX]) + shaded = false; + + equalizerwin = new EqWindow (shaded); + equalizerwin->setWindowTitle (_("Audacious Equalizer")); +} + +void equalizerwin_unhook () +{ + hook_dissociate ("set equalizer_active", (HookFunction) update_from_config); + hook_dissociate ("set equalizer_bands", (HookFunction) update_from_config); + hook_dissociate ("set equalizer_preamp", (HookFunction) update_from_config); +} + +void equalizerwin_create () +{ + equalizerwin_create_window (); + equalizerwin_create_widgets (); + + hook_associate ("set equalizer_active", (HookFunction) update_from_config, nullptr); + hook_associate ("set equalizer_bands", (HookFunction) update_from_config, nullptr); + hook_associate ("set equalizer_preamp", (HookFunction) update_from_config, nullptr); +} diff --git a/src/skins/equalizer.h b/src/skins/equalizer.h new file mode 100644 index 0000000..e2047f4 --- /dev/null +++ b/src/skins/equalizer.h @@ -0,0 +1,38 @@ +/* Audacious - Cross-platform multimedia player + * Copyright (C) 2005-2007 Audacious development team. + * + * Based on BMP: + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#ifndef SKINS_UI_EQUALIZER_H +#define SKINS_UI_EQUALIZER_H + +class Window; + +void equalizerwin_create (); +void equalizerwin_unhook (); +void equalizerwin_set_volume_slider (int percent); +void equalizerwin_set_balance_slider (int percent); + +extern Window * equalizerwin; + +#endif /* SKINS_UI_EQUALIZER_H */ diff --git a/src/skins/hslider.cc b/src/skins/hslider.cc new file mode 100644 index 0000000..fe259b2 --- /dev/null +++ b/src/skins/hslider.cc @@ -0,0 +1,129 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2011 John Lindgren + * + * Based on: + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include <libaudcore/objects.h> + +#include "skins_cfg.h" +#include "hslider.h" + +void HSlider::draw (cairo_t * cr) +{ + skin_draw_pixbuf (cr, m_si, m_fx, m_fy, 0, 0, m_w, m_h); + + if (m_pressed) + skin_draw_pixbuf (cr, m_si, m_kpx, m_kpy, m_pos, (m_h - m_kh) / 2, m_kw, m_kh); + else + skin_draw_pixbuf (cr, m_si, m_knx, m_kny, m_pos, (m_h - m_kh) / 2, m_kw, m_kh); +} + +bool HSlider::button_press (GdkEventButton * event) +{ + if (event->button != 1) + return false; + + m_pressed = true; + m_pos = aud::clamp ((int) event->x / config.scale - m_kw / 2, m_min, m_max); + + if (move) + move (); + + queue_draw (); + return true; +} + +bool HSlider::button_release (GdkEventButton * event) +{ + if (event->button != 1) + return false; + + if (! m_pressed) + return true; + + m_pressed = false; + m_pos = aud::clamp ((int) event->x / config.scale - m_kw / 2, m_min, m_max); + + if (release) + release (); + + queue_draw (); + return true; +} + +bool HSlider::motion (GdkEventMotion * event) +{ + if (! m_pressed) + return true; + + m_pressed = true; + m_pos = aud::clamp ((int) event->x / config.scale - m_kw / 2, m_min, m_max); + + if (move) + move (); + + queue_draw (); + return true; +} + +HSlider::HSlider (int min, int max, SkinPixmapId si, int w, int h, int fx, + int fy, int kw, int kh, int knx, int kny, int kpx, int kpy) : + m_min (min), m_max (max), m_si (si), m_w (w), m_h (h), m_fx (fx), m_fy (fy), + m_kw (kw), m_kh (kh), m_knx (knx), m_kny (kny), m_kpx (kpx), m_kpy (kpy) +{ + set_scale (config.scale); + add_input (w, h, true, true); +} + +void HSlider::set_frame (int fx, int fy) +{ + m_fx = fx; + m_fy = fy; + queue_draw (); +} + +void HSlider::set_knob (int knx, int kny, int kpx, int kpy) +{ + m_knx = knx; + m_kny = kny; + m_kpx = kpx; + m_kpy = kpy; + queue_draw (); +} + +void HSlider::set_pos (int pos) +{ + if (m_pressed) + return; + + m_pos = aud::clamp (pos, m_min, m_max); + queue_draw (); +} + +void HSlider::set_pressed (bool pressed) +{ + m_pressed = pressed; + queue_draw (); +} diff --git a/src/skins/hslider.h b/src/skins/hslider.h new file mode 100644 index 0000000..db15d04 --- /dev/null +++ b/src/skins/hslider.h @@ -0,0 +1,70 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2011 John Lindgren + * + * Based on: + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#ifndef SKINS_UI_SKINNED_HORIZONTAL_SLIDER_H +#define SKINS_UI_SKINNED_HORIZONTAL_SLIDER_H + +#include "widget.h" +#include "skin.h" + +class HSlider : public Widget +{ +public: + HSlider (int min, int max, SkinPixmapId si, int w, int h, int fx, int fy, + int kw, int kh, int knx, int kny, int kpx, int kpy); + + void set_frame (int fx, int fy); + void set_knob (int knx, int kny, int kpx, int kpy); + int get_pos () { return m_pos; } + void set_pos (int pos); + bool get_pressed () { return m_pressed; } + void set_pressed (bool pressed); + + void on_move (void (* callback) ()) { move = callback; } + void on_release (void (* callback) ()) { release = callback; } + +private: + void draw (cairo_t * cr); + bool button_press (GdkEventButton * event); + bool button_release (GdkEventButton * event); + bool motion (GdkEventMotion * event); + + int m_min, m_max; + SkinPixmapId m_si; + int m_w, m_h; + int m_fx, m_fy; + int m_kw, m_kh; + int m_knx, m_kny, m_kpx, m_kpy; + + int m_pos = 0; + bool m_pressed = false; + + void (* move) () = nullptr; + void (* release) () = nullptr; +}; + +#endif diff --git a/src/skins/main.cc b/src/skins/main.cc new file mode 100644 index 0000000..b8fc696 --- /dev/null +++ b/src/skins/main.cc @@ -0,0 +1,1227 @@ +/* Audacious - Cross-platform multimedia player + * Copyright (C) 2005-2011 Audacious development team. + * + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include <math.h> +#include <stdlib.h> +#include <string.h> +#include <sys/time.h> + +#include <gdk/gdkkeysyms.h> +#include <gtk/gtk.h> + +#include <libaudcore/audstrings.h> +#include <libaudcore/drct.h> +#include <libaudcore/hook.h> +#include <libaudcore/i18n.h> +#include <libaudcore/mainloop.h> +#include <libaudcore/plugins.h> +#include <libaudcore/runtime.h> +#include <libaudgui/libaudgui.h> + +#include "actions-mainwin.h" +#include "actions-playlist.h" +#include "dnd.h" +#include "menus.h" +#include "plugin.h" +#include "skins_cfg.h" +#include "equalizer.h" +#include "main.h" +#include "vis-callbacks.h" +#include "playlist.h" +#include "button.h" +#include "hslider.h" +#include "menurow.h" +#include "monostereo.h" +#include "number.h" +#include "playlist-widget.h" +#include "playstatus.h" +#include "textbox.h" +#include "window.h" +#include "vis.h" +#include "util.h" +#include "view.h" + +#define SEEK_THRESHOLD 200 /* milliseconds */ +#define SEEK_SPEED 50 /* milliseconds per pixel */ + +class MainWindow : public Window +{ +public: + MainWindow (bool shaded) : + Window (WINDOW_MAIN, & config.player_x, & config.player_y, + shaded ? MAINWIN_SHADED_WIDTH : skin.hints.mainwin_width, + shaded ? MAINWIN_SHADED_HEIGHT : skin.hints.mainwin_height, shaded) {} + +private: + void draw (cairo_t * cr); + bool button_press (GdkEventButton * event); + bool scroll (GdkEventScroll * event); +}; + +Window * mainwin; + +Button * mainwin_eq, * mainwin_pl; +TextBox * mainwin_info; +MenuRow * mainwin_menurow; + +SkinnedVis * mainwin_vis; +SmallVis * mainwin_svis; + +static bool seeking = false; +static int seek_start, seek_time; + +static TextBox * locked_textbox = nullptr; +static String locked_old_text; + +static QueuedFunc status_message_timeout; +static QueuedFunc mainwin_volume_release_timeout; + +static Button * mainwin_menubtn, * mainwin_minimize, * mainwin_shade, * mainwin_close; +static Button * mainwin_shaded_menubtn, * mainwin_shaded_minimize, * mainwin_shaded_shade, * mainwin_shaded_close; + +static Button * mainwin_rew, * mainwin_fwd; +static Button * mainwin_eject; +static Button * mainwin_play, * mainwin_pause, * mainwin_stop; +static Button * mainwin_shuffle, * mainwin_repeat; + +static TextBox * mainwin_stime_min, * mainwin_stime_sec; +static TextBox * mainwin_rate_text, * mainwin_freq_text, * mainwin_othertext; + +static PlayStatus * mainwin_playstatus; +static SkinnedNumber * mainwin_minus_num, * mainwin_10min_num, * mainwin_min_num; +static SkinnedNumber * mainwin_10sec_num, * mainwin_sec_num; +static HSlider * mainwin_position, * mainwin_sposition; + +static HSlider * mainwin_volume, * mainwin_balance; +static MonoStereo * mainwin_monostereo; + +static Button * mainwin_srew, * mainwin_splay, * mainwin_spause; +static Button * mainwin_sstop, * mainwin_sfwd, * mainwin_seject, * mainwin_about; + +static void mainwin_position_motion_cb (); +static void mainwin_position_release_cb (); +static void seek_timeout (void * rewind); + +static void format_time (char buf[7], int time, int length) +{ + bool zero = aud_get_bool (nullptr, "leading_zero"); + bool remaining = aud_get_bool ("skins", "show_remaining_time"); + + if (remaining && length > 0) + { + time = (length - time) / 1000; + + if (time < 60) + snprintf (buf, 7, zero ? "-00:%02d" : " -0:%02d", time); + else if (time < 6000) + snprintf (buf, 7, zero ? "%03d:%02d" : "%3d:%02d", -time / 60, time % 60); + else + snprintf (buf, 7, "%3d:%02d", -time / 3600, time / 60 % 60); + } + else + { + time /= 1000; + + if (time < 6000) + snprintf (buf, 7, zero ? " %02d:%02d" : " %2d:%02d", time / 60, time % 60); + else if (time < 60000) + snprintf (buf, 7, "%3d:%02d", time / 60, time % 60); + else + snprintf (buf, 7, "%3d:%02d", time / 3600, time / 60 % 60); + } +} + +static void mainwin_menubtn_cb () +{ + int x, y; + mainwin->getPosition (& x, & y); + menu_popup (UI_MENU_MAIN, x + 6 * config.scale, + y + MAINWIN_SHADED_HEIGHT * config.scale, false, false, 1, GDK_CURRENT_TIME); +} + +static void mainwin_minimize_cb () +{ + gtk_window_iconify ((GtkWindow *) mainwin->gtk ()); +} + +static void mainwin_shade_toggle () +{ + view_set_player_shaded (! aud_get_bool ("skins", "player_shaded")); +} + +static void mainwin_lock_info_text (const char * text) +{ + if (! locked_textbox) + { + locked_textbox = skin.hints.mainwin_othertext_is_status ? mainwin_othertext : mainwin_info; + locked_old_text = locked_textbox->get_text (); + } + + locked_textbox->set_text (text); +} + +static void mainwin_release_info_text (void * = nullptr) +{ + if (locked_textbox) + { + locked_textbox->set_text (locked_old_text); + locked_textbox = nullptr; + locked_old_text = String (); + } +} + +static void set_info_text (TextBox * textbox, const char * text) +{ + if (textbox == locked_textbox) + locked_old_text = String (text); + else + textbox->set_text (text); +} + +#define mainwin_set_info_text(t) set_info_text (mainwin_info, (t)) +#define mainwin_set_othertext(t) set_info_text (mainwin_othertext, (t)) + +void mainwin_show_status_message (const char * message) +{ + mainwin_lock_info_text (message); + status_message_timeout.queue (1000, mainwin_release_info_text, nullptr); +} + +static void mainwin_set_song_title (const char * title) +{ + if (title) + mainwin->setWindowTitle ((const char *) str_printf (_("%s - Audacious"), title)); + else + mainwin->setWindowTitle (_("Audacious")); + + mainwin_set_info_text (title ? title : ""); +} + +static void title_change () +{ + if (aud_drct_get_ready ()) + mainwin_set_song_title (aud_drct_get_title ()); + else + mainwin_set_song_title ("Buffering ..."); +} + +static void setup_widget (Widget * widget, int x, int y, bool show) +{ + int width, height; + + /* use get_size_request(), not get_preferred_size() */ + /* get_preferred_size() will return 0x0 for hidden widgets */ + gtk_widget_get_size_request (widget->gtk (), & width, & height); + + width /= config.scale; + height /= config.scale; + + /* hide widgets that are outside the window boundary */ + if (x < 0 || x + width > skin.hints.mainwin_width || + y < 0 || y + height > skin.hints.mainwin_height) + show = false; + + widget->setVisible (show); + mainwin->move_widget (false, widget, x, y); +} + +void mainwin_refresh_hints () +{ + const SkinHints * p = & skin.hints; + + mainwin_menurow->setVisible (p->mainwin_menurow_visible); + mainwin_rate_text->setVisible (p->mainwin_streaminfo_visible); + mainwin_freq_text->setVisible (p->mainwin_streaminfo_visible); + mainwin_monostereo->setVisible (p->mainwin_streaminfo_visible); + + mainwin_info->set_width (p->mainwin_text_width); + + setup_widget (mainwin_vis, p->mainwin_vis_x, p->mainwin_vis_y, p->mainwin_vis_visible); + setup_widget (mainwin_info, p->mainwin_text_x, p->mainwin_text_y, p->mainwin_text_visible); + setup_widget (mainwin_othertext, p->mainwin_infobar_x, p->mainwin_infobar_y, p->mainwin_othertext_visible); + + bool playing = aud_drct_get_playing (); + bool can_seek = aud_drct_get_length () > 0; + + setup_widget (mainwin_minus_num, p->mainwin_number_0_x, p->mainwin_number_0_y, playing); + setup_widget (mainwin_10min_num, p->mainwin_number_1_x, p->mainwin_number_1_y, playing); + setup_widget (mainwin_min_num, p->mainwin_number_2_x, p->mainwin_number_2_y, playing); + setup_widget (mainwin_10sec_num, p->mainwin_number_3_x, p->mainwin_number_3_y, playing); + setup_widget (mainwin_sec_num, p->mainwin_number_4_x, p->mainwin_number_4_y, playing); + setup_widget (mainwin_position, p->mainwin_position_x, p->mainwin_position_y, can_seek); + + setup_widget (mainwin_playstatus, p->mainwin_playstatus_x, p->mainwin_playstatus_y, true); + setup_widget (mainwin_volume, p->mainwin_volume_x, p->mainwin_volume_y, true); + setup_widget (mainwin_balance, p->mainwin_balance_x, p->mainwin_balance_y, true); + setup_widget (mainwin_rew, p->mainwin_previous_x, p->mainwin_previous_y, true); + setup_widget (mainwin_play, p->mainwin_play_x, p->mainwin_play_y, true); + setup_widget (mainwin_pause, p->mainwin_pause_x, p->mainwin_pause_y, true); + setup_widget (mainwin_stop, p->mainwin_stop_x, p->mainwin_stop_y, true); + setup_widget (mainwin_fwd, p->mainwin_next_x, p->mainwin_next_y, true); + setup_widget (mainwin_eject, p->mainwin_eject_x, p->mainwin_eject_y, true); + setup_widget (mainwin_eq, p->mainwin_eqbutton_x, p->mainwin_eqbutton_y, true); + setup_widget (mainwin_pl, p->mainwin_plbutton_x, p->mainwin_plbutton_y, true); + setup_widget (mainwin_shuffle, p->mainwin_shuffle_x, p->mainwin_shuffle_y, true); + setup_widget (mainwin_repeat, p->mainwin_repeat_x, p->mainwin_repeat_y, true); + setup_widget (mainwin_about, p->mainwin_about_x, p->mainwin_about_y, true); + setup_widget (mainwin_minimize, p->mainwin_minimize_x, p->mainwin_minimize_y, true); + setup_widget (mainwin_shade, p->mainwin_shade_x, p->mainwin_shade_y, true); + setup_widget (mainwin_close, p->mainwin_close_x, p->mainwin_close_y, true); + + if (aud_get_bool ("skins", "player_shaded")) + mainwin->resize (MAINWIN_SHADED_WIDTH, MAINWIN_SHADED_HEIGHT); + else + mainwin->resize (p->mainwin_width, p->mainwin_height); + + mainwin_vis->set_colors (); +} + +/* note that the song info is not translated since it is displayed using + * the skinned bitmap font, which supports only the English alphabet */ +static void mainwin_set_song_info (int bitrate, int samplerate, int channels) +{ + char scratch[32]; + int length; + + if (bitrate > 0) + { + if (bitrate < 1000000) + snprintf (scratch, sizeof scratch, "%3d", bitrate / 1000); + else + snprintf (scratch, sizeof scratch, "%2dH", bitrate / 100000); + + mainwin_rate_text->set_text (scratch); + } + else + mainwin_rate_text->set_text (nullptr); + + if (samplerate > 0) + { + snprintf (scratch, sizeof scratch, "%2d", samplerate / 1000); + mainwin_freq_text->set_text (scratch); + } + else + mainwin_freq_text->set_text (nullptr); + + mainwin_monostereo->set_num_channels (channels); + + if (bitrate > 0) + snprintf (scratch, sizeof scratch, "%d kbps", bitrate / 1000); + else + scratch[0] = 0; + + if (samplerate > 0) + { + length = strlen (scratch); + snprintf (scratch + length, sizeof scratch - length, "%s%d kHz", length ? + ", " : "", samplerate / 1000); + } + + if (channels > 0) + { + length = strlen (scratch); + snprintf (scratch + length, sizeof scratch - length, "%s%s", length ? + ", " : "", channels > 2 ? "surround" : channels > 1 ? "stereo" : "mono"); + } + + mainwin_set_othertext (scratch); +} + +static void info_change () +{ + int bitrate, samplerate, channels; + aud_drct_get_info (bitrate, samplerate, channels); + mainwin_set_song_info (bitrate, samplerate, channels); +} + +static void playback_pause () +{ + mainwin_playstatus->set_status (STATUS_PAUSE); +} + +static void playback_unpause () +{ + mainwin_playstatus->set_status (STATUS_PLAY); +} + +void mainwin_playback_begin () +{ + mainwin_update_song_info (); + + mainwin_stime_min->show (); + mainwin_stime_sec->show (); + mainwin_minus_num->show (); + mainwin_10min_num->show (); + mainwin_min_num->show (); + mainwin_10sec_num->show (); + mainwin_sec_num->show (); + + if (aud_drct_get_length () > 0) + { + mainwin_position->show (); + mainwin_sposition->show (); + } + + if (aud_drct_get_paused ()) + playback_pause (); + else + playback_unpause (); + + title_change (); + info_change (); +} + +static void mainwin_playback_stop () +{ + seeking = false; + timer_remove (TimerRate::Hz10, seek_timeout); + + mainwin_set_song_title (nullptr); + + mainwin_vis->clear (); + mainwin_svis->clear (); + + mainwin_minus_num->hide (); + mainwin_10min_num->hide (); + mainwin_min_num->hide (); + mainwin_10sec_num->hide (); + mainwin_sec_num->hide (); + mainwin_stime_min->hide (); + mainwin_stime_sec->hide (); + mainwin_position->hide (); + mainwin_sposition->hide (); + + mainwin_position->set_pressed (false); + mainwin_sposition->set_pressed (false); + + /* clear sampling parameter displays */ + mainwin_rate_text->set_text (nullptr); + mainwin_freq_text->set_text (nullptr); + mainwin_monostereo->set_num_channels (0); + mainwin_set_othertext (""); + + mainwin_playstatus->set_status (STATUS_STOP); + + playlistwin_hide_timer(); +} + +static void repeat_toggled () +{ + mainwin_repeat->set_active (aud_get_bool (nullptr, "repeat")); +} + +static void shuffle_toggled () +{ + mainwin_shuffle->set_active (aud_get_bool (nullptr, "shuffle")); +} + +static void no_advance_toggled () +{ + if (aud_get_bool (nullptr, "no_playlist_advance")) + mainwin_show_status_message (_("Single mode.")); + else + mainwin_show_status_message (_("Playlist mode.")); +} + +static void stop_after_song_toggled () +{ + if (aud_get_bool (nullptr, "stop_after_current_song")) + mainwin_show_status_message (_("Stopping after song.")); +} + +bool MainWindow::scroll (GdkEventScroll * event) +{ + switch (event->direction) + { + case GDK_SCROLL_UP: + mainwin_set_volume_diff (5); + break; + case GDK_SCROLL_DOWN: + mainwin_set_volume_diff (-5); + break; + case GDK_SCROLL_LEFT: + aud_drct_seek (aud_drct_get_time () - 5000); + break; + case GDK_SCROLL_RIGHT: + aud_drct_seek (aud_drct_get_time () + 5000); + break; + default: + break; + } + + return true; +} + +bool MainWindow::button_press (GdkEventButton * event) +{ + if (event->button == 1 && event->type == GDK_2BUTTON_PRESS && + event->window == gtk_widget_get_window (gtk ()) && + event->y < 14 * config.scale) + { + mainwin_shade_toggle (); + return true; + } + + if (event->button == 3 && event->type == GDK_BUTTON_PRESS) + { + menu_popup (UI_MENU_MAIN, event->x_root, event->y_root, false, false, + event->button, event->time); + return true; + } + + return Window::button_press (event); +} + +static void mainwin_playback_rpress (Button * button, GdkEventButton * event) +{ + menu_popup (UI_MENU_PLAYBACK, event->x_root, event->y_root, false, false, + event->button, event->time); +} + +bool Window::keypress (GdkEventKey * event) +{ + if (playlistwin_list->handle_keypress (event)) + return true; + + switch (event->keyval) + { + case GDK_KEY_Left: + case GDK_KEY_KP_Left: + case GDK_KEY_KP_7: + aud_drct_seek (aud_drct_get_time () - 5000); + break; + case GDK_KEY_Right: + case GDK_KEY_KP_Right: + case GDK_KEY_KP_9: + aud_drct_seek (aud_drct_get_time () + 5000); + break; + case GDK_KEY_KP_4: + aud_drct_pl_prev (); + break; + case GDK_KEY_KP_6: + aud_drct_pl_next (); + break; + case GDK_KEY_KP_Insert: + audgui_jump_to_track (); + break; + case GDK_KEY_space: + aud_drct_pause (); + break; + case GDK_KEY_Tab: /* GtkUIManager does not handle tab, apparently. */ + if (event->state & GDK_SHIFT_MASK) + action_playlist_prev (); + else + action_playlist_next (); + + break; + case GDK_KEY_ISO_Left_Tab: + action_playlist_prev (); + break; + default: + return false; + } + + return true; +} + +void mainwin_drag_data_received (GtkWidget * widget, GdkDragContext * context, + int x, int y, GtkSelectionData * selection_data, unsigned info, unsigned time, void *) +{ + g_return_if_fail (selection_data != nullptr); + + const char * data = (const char *) gtk_selection_data_get_data (selection_data); + g_return_if_fail (data); + + if (str_has_prefix_nocase (data, "file:///")) + { + if (str_has_suffix_nocase (data, ".wsz\r\n") || str_has_suffix_nocase + (data, ".zip\r\n")) + { + on_skin_view_drag_data_received (0, context, x, y, selection_data, info, time, 0); + return; + } + } + + audgui_urilist_open (data); +} + +static int time_now () +{ + struct timeval tv; + gettimeofday (& tv, nullptr); + return (tv.tv_sec % (24 * 3600) * 1000 + tv.tv_usec / 1000); +} + +static int time_diff (int a, int b) +{ + if (a > 18 * 3600 * 1000 && b < 6 * 3600 * 1000) /* detect midnight */ + b += 24 * 3600 * 1000; + return (b > a) ? b - a : 0; +} + +static void seek_timeout (void * rewind) +{ + int held = time_diff (seek_time, time_now ()); + if (held < SEEK_THRESHOLD) + return; + + int position; + if (aud::from_ptr<bool> (rewind)) + position = seek_start - held / SEEK_SPEED; + else + position = seek_start + held / SEEK_SPEED; + + position = aud::clamp (position, 0, 219); + mainwin_position->set_pos (position); + mainwin_position_motion_cb (); +} + +static void seek_press (GdkEventButton * event, bool rewind) +{ + if (event->button != 1 || seeking) + return; + + seeking = true; + seek_start = mainwin_position->get_pos (); + seek_time = time_now (); + timer_add (TimerRate::Hz10, seek_timeout, aud::to_ptr (rewind)); +} + +static void seek_release (GdkEventButton * event, bool rewind) +{ + if (event->button != 1 || ! seeking) + return; + + if (! aud_drct_get_playing () || time_diff (seek_time, time_now ()) < + SEEK_THRESHOLD) + { + if (rewind) + aud_drct_pl_prev (); + else + aud_drct_pl_next (); + } + else + mainwin_position_release_cb (); + + seeking = false; + timer_remove (TimerRate::Hz10, seek_timeout); +} + +static void mainwin_rew_press (Button * button, GdkEventButton * event) + { seek_press (event, true); } +static void mainwin_rew_release (Button * button, GdkEventButton * event) + { seek_release (event, true); } +static void mainwin_fwd_press (Button * button, GdkEventButton * event) + { seek_press (event, false); } +static void mainwin_fwd_release (Button * button, GdkEventButton * event) + { seek_release (event, false); } + +static void mainwin_shuffle_cb (Button * button, GdkEventButton * event) + { aud_set_bool (nullptr, "shuffle", button->get_active ()); } +static void mainwin_repeat_cb (Button * button, GdkEventButton * event) + { aud_set_bool (nullptr, "repeat", button->get_active ()); } +static void mainwin_eq_cb (Button * button, GdkEventButton * event) + { view_set_show_equalizer (button->get_active ()); } +static void mainwin_pl_cb (Button * button, GdkEventButton * event) + { view_set_show_playlist (button->get_active ()); } + +static void mainwin_spos_set_knob () +{ + int pos = mainwin_sposition->get_pos (); + int x = (pos < 6) ? 17 : (pos < 9) ? 20 : 23; + mainwin_sposition->set_knob (x, 36, x, 36); +} + +static void mainwin_spos_motion_cb () +{ + mainwin_spos_set_knob (); + + int pos = mainwin_sposition->get_pos (); + int length = aud_drct_get_length (); + int time = (pos - 1) * length / 12; + + char buf[7]; + format_time (buf, time, length); + + mainwin_stime_min->set_text (buf); + mainwin_stime_sec->set_text (buf + 4); +} + +static void mainwin_spos_release_cb () +{ + mainwin_spos_set_knob (); + + int pos = mainwin_sposition->get_pos (); + aud_drct_seek (aud_drct_get_length () * (pos - 1) / 12); +} + +static void mainwin_position_motion_cb () +{ + int length = aud_drct_get_length () / 1000; + int pos = mainwin_position->get_pos (); + int time = pos * length / 219; + + mainwin_lock_info_text (str_printf (_("Seek to %d:%-2.2d / %d:%-2.2d"), + time / 60, time % 60, length / 60, length % 60)); +} + +static void mainwin_position_release_cb () +{ + int length = aud_drct_get_length (); + int pos = mainwin_position->get_pos (); + int time = (int64_t) pos * length / 219; + + aud_drct_seek(time); + mainwin_release_info_text(); +} + +void mainwin_adjust_volume_motion (int v) +{ + aud_drct_set_volume_main (v); + mainwin_lock_info_text (str_printf (_("Volume: %d%%"), v)); +} + +void mainwin_adjust_volume_release () +{ + mainwin_release_info_text (); +} + +void mainwin_adjust_balance_motion (int b) +{ + aud_drct_set_volume_balance (b); + + if (b < 0) + mainwin_lock_info_text (str_printf (_("Balance: %d%% left"), -b)); + else if (b == 0) + mainwin_lock_info_text (_("Balance: center")); + else + mainwin_lock_info_text (str_printf (_("Balance: %d%% right"), b)); +} + +void mainwin_adjust_balance_release () +{ + mainwin_release_info_text (); +} + +static void mainwin_volume_set_frame () +{ + int pos = mainwin_volume->get_pos (); + int frame = (pos * 27 + 25) / 51; + mainwin_volume->set_frame (0, 15 * frame); +} + +void mainwin_set_volume_slider (int percent) +{ + mainwin_volume->set_pos ((percent * 51 + 50) / 100); + mainwin_volume_set_frame (); +} + +static void mainwin_volume_motion_cb () +{ + mainwin_volume_set_frame (); + int pos = mainwin_volume->get_pos (); + int vol = (pos * 100 + 25) / 51; + + mainwin_adjust_volume_motion (vol); + equalizerwin_set_volume_slider (vol); +} + +static void mainwin_volume_release_cb () +{ + mainwin_volume_set_frame (); + mainwin_adjust_volume_release (); +} + +static void mainwin_balance_set_frame () +{ + int pos = mainwin_balance->get_pos (); + int frame = (abs (pos - 12) * 27 + 6) / 12; + mainwin_balance->set_frame (9, 15 * frame); +} + +void mainwin_set_balance_slider (int percent) +{ + if (percent > 0) + mainwin_balance->set_pos (12 + (percent * 12 + 50) / 100); + else + mainwin_balance->set_pos (12 + (percent * 12 - 50) / 100); + + mainwin_balance_set_frame (); +} + +static void mainwin_balance_motion_cb () +{ + mainwin_balance_set_frame (); + int pos = mainwin_balance->get_pos (); + + int bal; + if (pos > 12) + bal = ((pos - 12) * 100 + 6) / 12; + else + bal = ((pos - 12) * 100 - 6) / 12; + + mainwin_adjust_balance_motion (bal); + equalizerwin_set_balance_slider (bal); +} + +static void mainwin_balance_release_cb () +{ + mainwin_balance_set_frame (); + mainwin_adjust_volume_release (); +} + +void mainwin_set_volume_diff (int diff) +{ + int vol = aud_drct_get_volume_main (); + + vol = aud::clamp (vol + diff, 0, 100); + mainwin_adjust_volume_motion (vol); + mainwin_set_volume_slider (vol); + equalizerwin_set_volume_slider (vol); + + mainwin_volume_release_timeout.queue (700, + [] (void *) { mainwin_volume_release_cb (); }, nullptr); +} + +void mainwin_mr_change (MenuRowItem i) +{ + switch (i) + { + case MENUROW_OPTIONS: + mainwin_lock_info_text (_("Options Menu")); + break; + case MENUROW_ALWAYS: + if (aud_get_bool ("skins", "always_on_top")) + mainwin_lock_info_text (_("Disable 'Always On Top'")); + else + mainwin_lock_info_text (_("Enable 'Always On Top'")); + break; + case MENUROW_FILEINFOBOX: + mainwin_lock_info_text (_("File Info Box")); + break; + case MENUROW_SCALE: + mainwin_lock_info_text (_("Double Size")); + break; + case MENUROW_VISUALIZATION: + mainwin_lock_info_text (_("Visualizations")); + break; + default: + break; + } +} + +void mainwin_mr_release (MenuRowItem i, GdkEventButton * event) +{ + switch (i) + { + case MENUROW_OPTIONS: + menu_popup (UI_MENU_VIEW, event->x_root, event->y_root, false, false, 1, event->time); + break; + case MENUROW_ALWAYS: + view_set_on_top (! aud_get_bool ("skins", "always_on_top")); + break; + case MENUROW_FILEINFOBOX: + audgui_infowin_show_current (); + break; + case MENUROW_SCALE: + view_set_double_size (! aud_get_bool ("skins", "double_size")); + break; + case MENUROW_VISUALIZATION: + audgui_show_prefs_for_plugin_type (PluginType::Vis); + break; + default: + break; + } + + mainwin_release_info_text(); +} + +bool change_timer_mode_cb (GdkEventButton * event) +{ + if (event->type != GDK_BUTTON_PRESS || event->button != 1) + return false; + + view_set_show_remaining (! aud_get_bool ("skins", "show_remaining_time")); + return true; +} + +static bool mainwin_info_button_press (GdkEventButton * event) +{ + if (event->type == GDK_BUTTON_PRESS && event->button == 3) + { + menu_popup (UI_MENU_PLAYBACK, event->x_root, event->y_root, false, + false, event->button, event->time); + return true; + } + + if (event->type == GDK_2BUTTON_PRESS && event->button == 1) + { + audgui_infowin_show_current (); + return true; + } + + return false; +} + +static void mainwin_create_widgets () +{ + mainwin_menubtn = new Button (9, 9, 0, 0, 0, 9, SKIN_TITLEBAR, SKIN_TITLEBAR); + mainwin->put_widget (false, mainwin_menubtn, 6, 3); + mainwin_menubtn->on_release ((ButtonCB) mainwin_menubtn_cb); + + mainwin_minimize = new Button (9, 9, 9, 0, 9, 9, SKIN_TITLEBAR, SKIN_TITLEBAR); + mainwin->put_widget (false, mainwin_minimize, 244, 3); + mainwin_minimize->on_release ((ButtonCB) mainwin_minimize_cb); + + mainwin_shade = new Button (9, 9, 0, 18, 9, 18, SKIN_TITLEBAR, SKIN_TITLEBAR); + mainwin->put_widget (false, mainwin_shade, 254, 3); + mainwin_shade->on_release ((ButtonCB) mainwin_shade_toggle); + + mainwin_close = new Button (9, 9, 18, 0, 18, 9, SKIN_TITLEBAR, SKIN_TITLEBAR); + mainwin->put_widget (false, mainwin_close, 264, 3); + mainwin_close->on_release ((ButtonCB) skins_close); + + mainwin_rew = new Button (23, 18, 0, 0, 0, 18, SKIN_CBUTTONS, SKIN_CBUTTONS); + mainwin->put_widget (false, mainwin_rew, 16, 88); + mainwin_rew->on_press (mainwin_rew_press); + mainwin_rew->on_release (mainwin_rew_release); + mainwin_rew->on_rpress (mainwin_playback_rpress); + + mainwin_fwd = new Button (22, 18, 92, 0, 92, 18, SKIN_CBUTTONS, SKIN_CBUTTONS); + mainwin->put_widget (false, mainwin_fwd, 108, 88); + mainwin_fwd->on_press (mainwin_fwd_press); + mainwin_fwd->on_release (mainwin_fwd_release); + mainwin_fwd->on_rpress (mainwin_playback_rpress); + + mainwin_play = new Button (23, 18, 23, 0, 23, 18, SKIN_CBUTTONS, SKIN_CBUTTONS); + mainwin->put_widget (false, mainwin_play, 39, 88); + mainwin_play->on_release ((ButtonCB) aud_drct_play); + mainwin_play->on_rpress (mainwin_playback_rpress); + + mainwin_pause = new Button (23, 18, 46, 0, 46, 18, SKIN_CBUTTONS, SKIN_CBUTTONS); + mainwin->put_widget (false, mainwin_pause, 62, 88); + mainwin_pause->on_release ((ButtonCB) aud_drct_pause); + mainwin_pause->on_rpress (mainwin_playback_rpress); + + mainwin_stop = new Button (23, 18, 69, 0, 69, 18, SKIN_CBUTTONS, SKIN_CBUTTONS); + mainwin->put_widget (false, mainwin_stop, 85, 88); + mainwin_stop->on_release ((ButtonCB) aud_drct_stop); + mainwin_stop->on_rpress (mainwin_playback_rpress); + + mainwin_eject = new Button (22, 16, 114, 0, 114, 16, SKIN_CBUTTONS, SKIN_CBUTTONS); + mainwin->put_widget (false, mainwin_eject, 136, 89); + mainwin_eject->on_release ((ButtonCB) action_play_file); + + mainwin_shuffle = new Button (46, 15, 28, 0, 28, 15, 28, 30, 28, 45, SKIN_SHUFREP, SKIN_SHUFREP); + mainwin->put_widget (false, mainwin_shuffle, 164, 89); + mainwin_shuffle->set_active (aud_get_bool (nullptr, "shuffle")); + mainwin_shuffle->on_release (mainwin_shuffle_cb); + + mainwin_repeat = new Button (28, 15, 0, 0, 0, 15, 0, 30, 0, 45, SKIN_SHUFREP, SKIN_SHUFREP); + mainwin->put_widget (false, mainwin_repeat, 210, 89); + mainwin_repeat->set_active (aud_get_bool (nullptr, "repeat")); + mainwin_repeat->on_release (mainwin_repeat_cb); + + mainwin_eq = new Button (23, 12, 0, 61, 46, 61, 0, 73, 46, 73, SKIN_SHUFREP, SKIN_SHUFREP); + mainwin->put_widget (false, mainwin_eq, 219, 58); + mainwin_eq->on_release (mainwin_eq_cb); + + mainwin_pl = new Button (23, 12, 23, 61, 69, 61, 23, 73, 69, 73, SKIN_SHUFREP, SKIN_SHUFREP); + mainwin->put_widget (false, mainwin_pl, 242, 58); + mainwin_pl->on_release (mainwin_pl_cb); + + String font; + if (! config.mainwin_use_bitmapfont) + font = aud_get_str ("skins", "mainwin_font"); + + bool shaded = aud_get_bool ("skins", "mainwin_shaded"); + mainwin_info = new TextBox (153, font, ! shaded && config.autoscroll); + mainwin->put_widget (false, mainwin_info, 112, 27); + mainwin_info->on_press (mainwin_info_button_press); + + mainwin_othertext = new TextBox (153, nullptr, false); + mainwin->put_widget (false, mainwin_othertext, 112, 43); + + mainwin_rate_text = new TextBox (15, nullptr, false); + mainwin->put_widget (false, mainwin_rate_text, 111, 43); + + mainwin_freq_text = new TextBox (10, nullptr, false); + mainwin->put_widget (false, mainwin_freq_text, 156, 43); + + mainwin_menurow = new MenuRow; + mainwin->put_widget (false, mainwin_menurow, 10, 22); + + mainwin_volume = new HSlider (0, 51, SKIN_VOLUME, 68, 13, 0, 0, 14, 11, 15, 422, 0, 422); + mainwin->put_widget (false, mainwin_volume, 107, 57); + mainwin_volume->on_move (mainwin_volume_motion_cb); + mainwin_volume->on_release (mainwin_volume_release_cb); + + mainwin_balance = new HSlider (0, 24, SKIN_BALANCE, 38, 13, 9, 0, 14, 11, 15, 422, 0, 422); + mainwin->put_widget (false, mainwin_balance, 177, 57); + mainwin_balance->on_move (mainwin_balance_motion_cb); + mainwin_balance->on_release (mainwin_balance_release_cb); + + mainwin_monostereo = new MonoStereo; + mainwin->put_widget (false, mainwin_monostereo, 212, 41); + + mainwin_playstatus = new PlayStatus; + mainwin->put_widget (false, mainwin_playstatus, 24, 28); + + mainwin_minus_num = new SkinnedNumber; + mainwin->put_widget (false, mainwin_minus_num, 36, 26); + + mainwin_10min_num = new SkinnedNumber; + mainwin->put_widget (false, mainwin_10min_num, 48, 26); + + mainwin_min_num = new SkinnedNumber; + mainwin->put_widget (false, mainwin_min_num, 60, 26); + + mainwin_10sec_num = new SkinnedNumber; + mainwin->put_widget (false, mainwin_10sec_num, 78, 26); + + mainwin_sec_num = new SkinnedNumber; + mainwin->put_widget (false, mainwin_sec_num, 90, 26); + + mainwin_about = new Button (20, 25); + mainwin->put_widget (false, mainwin_about, 247, 83); + mainwin_about->on_release ((ButtonCB) audgui_show_about_window); + + mainwin_vis = new SkinnedVis; + mainwin->put_widget (false, mainwin_vis, 24, 43); + + mainwin_position = new HSlider (0, 219, SKIN_POSBAR, 248, 10, 0, 0, 29, 10, 248, 0, 278, 0); + mainwin->put_widget (false, mainwin_position, 16, 72); + mainwin_position->on_move (mainwin_position_motion_cb); + mainwin_position->on_release (mainwin_position_release_cb); + + /* shaded */ + + mainwin_shaded_menubtn = new Button (9, 9, 0, 0, 0, 9, SKIN_TITLEBAR, SKIN_TITLEBAR); + mainwin->put_widget (true, mainwin_shaded_menubtn, 6, 3); + mainwin_shaded_menubtn->on_release ((ButtonCB) mainwin_menubtn_cb); + + mainwin_shaded_minimize = new Button (9, 9, 9, 0, 9, 9, SKIN_TITLEBAR, SKIN_TITLEBAR); + mainwin->put_widget (true, mainwin_shaded_minimize, 244, 3); + mainwin_shaded_minimize->on_release ((ButtonCB) mainwin_minimize_cb); + + mainwin_shaded_shade = new Button (9, 9, 0, 27, 9, 27, SKIN_TITLEBAR, SKIN_TITLEBAR); + mainwin->put_widget (true, mainwin_shaded_shade, 254, 3); + mainwin_shaded_shade->on_release ((ButtonCB) mainwin_shade_toggle); + + mainwin_shaded_close = new Button (9, 9, 18, 0, 18, 9, SKIN_TITLEBAR, SKIN_TITLEBAR); + mainwin->put_widget (true, mainwin_shaded_close, 264, 3); + mainwin_shaded_close->on_release ((ButtonCB) skins_close); + + mainwin_srew = new Button (8, 7); + mainwin->put_widget (true, mainwin_srew, 169, 4); + mainwin_srew->on_release ((ButtonCB) aud_drct_pl_prev); + + mainwin_splay = new Button (10, 7); + mainwin->put_widget (true, mainwin_splay, 177, 4); + mainwin_splay->on_release ((ButtonCB) aud_drct_play); + + mainwin_spause = new Button (10, 7); + mainwin->put_widget (true, mainwin_spause, 187, 4); + mainwin_spause->on_release ((ButtonCB) aud_drct_pause); + + mainwin_sstop = new Button (9, 7); + mainwin->put_widget (true, mainwin_sstop, 197, 4); + mainwin_sstop->on_release ((ButtonCB) aud_drct_stop); + + mainwin_sfwd = new Button (8, 7); + mainwin->put_widget (true, mainwin_sfwd, 206, 4); + mainwin_sfwd->on_release ((ButtonCB) aud_drct_pl_next); + + mainwin_seject = new Button (9, 7); + mainwin->put_widget (true, mainwin_seject, 216, 4); + mainwin_seject->on_release ((ButtonCB) action_play_file); + + mainwin_svis = new SmallVis (); + mainwin->put_widget (true, mainwin_svis, 79, 5); + + mainwin_sposition = new HSlider (1, 13, SKIN_TITLEBAR, 17, 7, 0, 36, 3, 7, 17, 36, 17, 36); + mainwin->put_widget (true, mainwin_sposition, 226, 4); + mainwin_sposition->on_move (mainwin_spos_motion_cb); + mainwin_sposition->on_release (mainwin_spos_release_cb); + + mainwin_stime_min = new TextBox (15, nullptr, false); + mainwin->put_widget (true, mainwin_stime_min, 130, 4); + mainwin_stime_min->on_press (change_timer_mode_cb); + + mainwin_stime_sec = new TextBox (10, nullptr, false); + mainwin->put_widget (true, mainwin_stime_sec, 147, 4); + mainwin_stime_sec->on_press (change_timer_mode_cb); +} + +static gboolean state_cb (GtkWidget * widget, GdkEventWindowState * event, void *) +{ + if (event->changed_mask & GDK_WINDOW_STATE_STICKY) + view_set_sticky (!! (event->new_window_state & GDK_WINDOW_STATE_STICKY)); + + if (event->changed_mask & GDK_WINDOW_STATE_ABOVE) + view_set_on_top (!! (event->new_window_state & GDK_WINDOW_STATE_ABOVE)); + + return true; +} + +void MainWindow::draw (cairo_t * cr) +{ + int width = is_shaded () ? MAINWIN_SHADED_WIDTH : skin.hints.mainwin_width; + int height = is_shaded () ? MAINWIN_SHADED_HEIGHT : skin.hints.mainwin_height; + + skin_draw_pixbuf (cr, SKIN_MAIN, 0, 0, 0, 0, width, height); + skin_draw_mainwin_titlebar (cr, is_shaded (), true); +} + +static void mainwin_create_window () +{ + bool shaded = aud_get_bool ("skins", "player_shaded"); + + mainwin = new MainWindow (shaded); + mainwin->setWindowTitle (_("Audacious")); + + GtkWidget * w = mainwin->gtk (); + drag_dest_set (w); + + g_signal_connect (w, "drag-data-received", (GCallback) mainwin_drag_data_received, nullptr); + g_signal_connect (w, "window-state-event", (GCallback) state_cb, nullptr); + + hook_associate ("playback begin", (HookFunction) mainwin_playback_begin, nullptr); + hook_associate ("playback ready", (HookFunction) mainwin_playback_begin, nullptr); + hook_associate ("playback seek", (HookFunction) mainwin_update_song_info, nullptr); + hook_associate ("playback stop", (HookFunction) mainwin_playback_stop, nullptr); + hook_associate ("playback pause", (HookFunction) playback_pause, nullptr); + hook_associate ("playback unpause", (HookFunction) playback_unpause, nullptr); + hook_associate ("title change", (HookFunction) title_change, nullptr); + hook_associate ("info change", (HookFunction) info_change, nullptr); + hook_associate ("set repeat", (HookFunction) repeat_toggled, nullptr); + hook_associate ("set shuffle", (HookFunction) shuffle_toggled, nullptr); + hook_associate ("set no_playlist_advance", (HookFunction) no_advance_toggled, nullptr); + hook_associate ("set stop_after_current_song", (HookFunction) stop_after_song_toggled, nullptr); +} + +void mainwin_unhook () +{ + seeking = false; + timer_remove (TimerRate::Hz10, seek_timeout); + + status_message_timeout.stop (); + mainwin_volume_release_timeout.stop (); + + hook_dissociate ("playback begin", (HookFunction) mainwin_playback_begin); + hook_dissociate ("playback ready", (HookFunction) mainwin_playback_begin); + hook_dissociate ("playback seek", (HookFunction) mainwin_update_song_info); + hook_dissociate ("playback stop", (HookFunction) mainwin_playback_stop); + hook_dissociate ("playback pause", (HookFunction) playback_pause); + hook_dissociate ("playback unpause", (HookFunction) playback_unpause); + hook_dissociate ("title change", (HookFunction) title_change); + hook_dissociate ("info change", (HookFunction) info_change); + hook_dissociate ("set repeat", (HookFunction) repeat_toggled); + hook_dissociate ("set shuffle", (HookFunction) shuffle_toggled); + hook_dissociate ("set no_playlist_advance", (HookFunction) no_advance_toggled); + hook_dissociate ("set stop_after_current_song", (HookFunction) stop_after_song_toggled); + + start_stop_visual (true); + + locked_textbox = nullptr; + locked_old_text = String (); +} + +void mainwin_create () +{ + mainwin_create_window (); + mainwin_create_widgets (); +} + +static void mainwin_update_volume () +{ + int volume = aud_drct_get_volume_main (); + int balance = aud_drct_get_volume_balance (); + + mainwin_set_volume_slider (volume); + mainwin_set_balance_slider (balance); + equalizerwin_set_volume_slider (volume); + equalizerwin_set_balance_slider (balance); +} + +static void mainwin_update_time_display (int time, int length) +{ + char scratch[7]; + format_time (scratch, time, length); + + mainwin_minus_num->set (scratch[0]); + mainwin_10min_num->set (scratch[1]); + mainwin_min_num->set (scratch[2]); + mainwin_10sec_num->set (scratch[4]); + mainwin_sec_num->set (scratch[5]); + + if (! mainwin_sposition->get_pressed ()) + { + mainwin_stime_min->set_text (scratch); + mainwin_stime_sec->set_text (scratch + 4); + } + + playlistwin_set_time (scratch, scratch + 4); +} + +static void mainwin_update_time_slider (int time, int length) +{ + mainwin_position->setVisible (length > 0); + mainwin_sposition->setVisible (length > 0); + + if (length > 0 && ! seeking) + { + if (time < length) + { + mainwin_position->set_pos (time * (int64_t) 219 / length); + mainwin_sposition->set_pos (1 + time * (int64_t) 12 / length); + } + else + { + mainwin_position->set_pos (219); + mainwin_sposition->set_pos (13); + } + + mainwin_spos_set_knob (); + } +} + +void mainwin_update_song_info () +{ + mainwin_update_volume (); + + if (! aud_drct_get_playing ()) + return; + + int time = 0, length = 0; + if (aud_drct_get_ready ()) + { + time = aud_drct_get_time (); + length = aud_drct_get_length (); + } + + mainwin_update_time_display (time, length); + mainwin_update_time_slider (time, length); +} diff --git a/src/skins/main.h b/src/skins/main.h new file mode 100644 index 0000000..5f590ee --- /dev/null +++ b/src/skins/main.h @@ -0,0 +1,73 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#ifndef SKINS_UI_MAIN_H +#define SKINS_UI_MAIN_H + +#include <gtk/gtk.h> + +/* yes, main window size is fixed */ +#define MAINWIN_WIDTH (int)275 +#define MAINWIN_HEIGHT (int)116 +#define MAINWIN_SHADED_WIDTH MAINWIN_WIDTH +#define MAINWIN_SHADED_HEIGHT (int)14 + +class Button; +class MenuRow; +class SkinnedVis; +class SmallVis; +class TextBox; +class Window; + +extern Window * mainwin; + +extern Button * mainwin_eq, * mainwin_pl; +extern TextBox * mainwin_info; +extern MenuRow * mainwin_menurow; + +extern SkinnedVis * mainwin_vis; +extern SmallVis * mainwin_svis; + +void mainwin_create (); +void mainwin_unhook (); + +void mainwin_adjust_volume_motion (int v); +void mainwin_adjust_volume_release (); +void mainwin_adjust_balance_motion (int b); +void mainwin_adjust_balance_release (); +void mainwin_set_volume_slider (int percent); +void mainwin_set_balance_slider (int percent); +void mainwin_set_volume_diff (int diff); + +void mainwin_refresh_hints (); +void mainwin_playback_begin (); + +void mainwin_update_song_info (); +void mainwin_show_status_message (const char * message); + +void mainwin_drag_data_received (GtkWidget * widget, + GdkDragContext * context, int x, int y, GtkSelectionData * selection_data, + unsigned info, unsigned time, void * data); + +bool change_timer_mode_cb (GdkEventButton * event); + +#endif /* SKINS_UI_MAIN_H */ diff --git a/src/skins/ui_skinned_menurow.cc b/src/skins/menurow.cc index ebd722d..820957d 100644 --- a/src/skins/ui_skinned_menurow.cc +++ b/src/skins/menurow.cc @@ -27,36 +27,30 @@ #include <libaudcore/runtime.h> -#include "draw-compat.h" #include "skins_cfg.h" -#include "ui_skin.h" -#include "ui_skinned_menurow.h" +#include "skin.h" +#include "menurow.h" -static struct { - MenuRowItem selected; - gboolean pushed; -} mr; - -DRAW_FUNC_BEGIN (menurow_draw) - if (mr.selected == MENUROW_NONE) +void MenuRow::draw (cairo_t * cr) +{ + if (m_selected == MENUROW_NONE) { - if (mr.pushed) + if (m_pushed) skin_draw_pixbuf (cr, SKIN_TITLEBAR, 304, 0, 0, 0, 8, 43); else skin_draw_pixbuf (cr, SKIN_TITLEBAR, 312, 0, 0, 0, 8, 43); } else - skin_draw_pixbuf (cr, SKIN_TITLEBAR, 304 + 8 * (mr.selected - 1), 44, 0, - 0, 8, 43); + skin_draw_pixbuf (cr, SKIN_TITLEBAR, 304 + 8 * (m_selected - 1), 44, 0, 0, 8, 43); - if (mr.pushed) + if (m_pushed) { if (aud_get_bool ("skins", "always_on_top")) skin_draw_pixbuf (cr, SKIN_TITLEBAR, 312, 54, 0, 10, 8, 8); if (aud_get_bool ("skins", "double_size")) skin_draw_pixbuf (cr, SKIN_TITLEBAR, 328, 70, 0, 26, 8, 8); } -DRAW_FUNC_END +} static MenuRowItem menurow_find_selected (int x, int y) { @@ -77,71 +71,52 @@ static MenuRowItem menurow_find_selected (int x, int y) return MENUROW_NONE; } -static gboolean menurow_button_press (GtkWidget * widget, GdkEventButton * event) +bool MenuRow::button_press (GdkEventButton * event) { if (event->button != 1) - return FALSE; + return false; - mr.pushed = TRUE; - mr.selected = menurow_find_selected (event->x / config.scale, event->y / config.scale); + m_pushed = true; + m_selected = menurow_find_selected (event->x / config.scale, event->y / config.scale); - mainwin_mr_change (mr.selected); + mainwin_mr_change (m_selected); - gtk_widget_queue_draw (widget); - return TRUE; + queue_draw (); + return true; } -static gboolean menurow_button_release (GtkWidget * widget, GdkEventButton * - event) +bool MenuRow::button_release (GdkEventButton * event) { if (event->button != 1) - return FALSE; + return false; - if (! mr.pushed) - return TRUE; + if (! m_pushed) + return true; - mainwin_mr_release (mr.selected, event); + mainwin_mr_release (m_selected, event); - mr.pushed = FALSE; - mr.selected = MENUROW_NONE; + m_pushed = false; + m_selected = MENUROW_NONE; - gtk_widget_queue_draw (widget); - return TRUE; + queue_draw (); + return true; } -static gboolean menurow_motion_notify (GtkWidget * widget, GdkEventMotion * - event) +bool MenuRow::motion (GdkEventMotion * event) { - if (! mr.pushed) - return TRUE; + if (! m_pushed) + return true; - mr.selected = menurow_find_selected (event->x / config.scale, event->y / config.scale); + m_selected = menurow_find_selected (event->x / config.scale, event->y / config.scale); - mainwin_mr_change (mr.selected); + mainwin_mr_change (m_selected); - gtk_widget_queue_draw (widget); - return TRUE; -} - -GtkWidget * ui_skinned_menurow_new (void) -{ - GtkWidget * wid = gtk_drawing_area_new (); - gtk_widget_set_size_request (wid, 8 * config.scale, 43 * config.scale); - gtk_widget_add_events (wid, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - | GDK_POINTER_MOTION_MASK); - - DRAW_CONNECT (wid, menurow_draw); - g_signal_connect (wid, "button-press-event", (GCallback) - menurow_button_press, nullptr); - g_signal_connect (wid, "button-release-event", (GCallback) - menurow_button_release, nullptr); - g_signal_connect (wid, "motion-notify-event", (GCallback) - menurow_motion_notify, nullptr); - - return wid; + queue_draw (); + return true; } -void ui_skinned_menurow_update (GtkWidget * menurow) +MenuRow::MenuRow () { - gtk_widget_queue_draw (menurow); + set_scale (config.scale); + add_input (8, 43, true, true); } diff --git a/src/skins/ui_skinned_menurow.h b/src/skins/menurow.h index b3d2682..b59e33c 100644 --- a/src/skins/ui_skinned_menurow.h +++ b/src/skins/menurow.h @@ -28,15 +28,32 @@ #ifndef SKINS_UI_SKINNED_MENUROW_H #define SKINS_UI_SKINNED_MENUROW_H -#include <gtk/gtk.h> +#include "widget.h" -typedef enum { - MENUROW_NONE, MENUROW_OPTIONS, MENUROW_ALWAYS, MENUROW_FILEINFOBOX, - MENUROW_SCALE, MENUROW_VISUALIZATION -} MenuRowItem; +enum MenuRowItem { + MENUROW_NONE, + MENUROW_OPTIONS, + MENUROW_ALWAYS, + MENUROW_FILEINFOBOX, + MENUROW_SCALE, + MENUROW_VISUALIZATION +}; -GtkWidget * ui_skinned_menurow_new (void); -void ui_skinned_menurow_update (GtkWidget * menurow); +class MenuRow : public Widget +{ +public: + MenuRow (); + void refresh () { queue_draw (); } + +private: + virtual void draw (cairo_t * cr); + virtual bool button_press (GdkEventButton * event); + virtual bool button_release (GdkEventButton * event); + virtual bool motion (GdkEventMotion * event); + + MenuRowItem m_selected = MENUROW_NONE; + bool m_pushed = false; +}; /* callbacks in ui_main.c */ void mainwin_mr_change (MenuRowItem i); diff --git a/src/skins/menus.cc b/src/skins/menus.cc index 66925e9..8c3a435 100644 --- a/src/skins/menus.cc +++ b/src/skins/menus.cc @@ -24,8 +24,11 @@ #include <gdk/gdkkeysyms.h> #include <libaudcore/drct.h> +#include <libaudcore/hook.h> #include <libaudcore/i18n.h> #include <libaudcore/interface.h> +#include <libaudcore/playlist.h> +#include <libaudcore/plugins.h> #include <libaudcore/runtime.h> #include <libaudgui/libaudgui.h> #include <libaudgui/libaudgui-gtk.h> @@ -33,8 +36,7 @@ #include "actions-mainwin.h" #include "actions-playlist.h" -#include "preset-browser.h" -#include "preset-list.h" +#include "main.h" #include "view.h" #define SHIFT GDK_SHIFT_MASK @@ -51,14 +53,55 @@ static GtkWidget * menus[UI_MENUS]; static GtkAccelGroup * accel; /* note: playback, playlist, and view menus must be created before main menu */ -static GtkWidget * get_menu_playback (void) {return menus[UI_MENU_PLAYBACK]; } -static GtkWidget * get_menu_playlist (void) {return menus[UI_MENU_PLAYLIST]; } -static GtkWidget * get_menu_view (void) {return menus[UI_MENU_VIEW]; } +static GtkWidget * get_menu_playback () { return menus[UI_MENU_PLAYBACK]; } +static GtkWidget * get_menu_playlist () { return menus[UI_MENU_PLAYLIST]; } +static GtkWidget * get_menu_view () { return menus[UI_MENU_VIEW]; } -static GtkWidget * get_plugin_menu_main (void) {return audgui_get_plugin_menu (AudMenuID::Main); } -static GtkWidget * get_plugin_menu_playlist (void) {return audgui_get_plugin_menu (AudMenuID::Playlist); } -static GtkWidget * get_plugin_menu_playlist_add (void) {return audgui_get_plugin_menu (AudMenuID::PlaylistAdd); } -static GtkWidget * get_plugin_menu_playlist_remove (void) {return audgui_get_plugin_menu (AudMenuID::PlaylistRemove); } +static GtkWidget * get_plugin_menu_main () { return audgui_get_plugin_menu (AudMenuID::Main); } +static GtkWidget * get_plugin_menu_playlist () { return audgui_get_plugin_menu (AudMenuID::Playlist); } +static GtkWidget * get_plugin_menu_playlist_add () { return audgui_get_plugin_menu (AudMenuID::PlaylistAdd); } +static GtkWidget * get_plugin_menu_playlist_remove () { return audgui_get_plugin_menu (AudMenuID::PlaylistRemove); } + +static void configure_effects () { audgui_show_prefs_for_plugin_type (PluginType::Effect); } +static void configure_output () { audgui_show_prefs_for_plugin_type (PluginType::Output); } +static void configure_visualizations () { audgui_show_prefs_for_plugin_type (PluginType::Vis); } + +static void volume_up () { mainwin_set_volume_diff (5); } +static void volume_down () { mainwin_set_volume_diff (-5); } + +/* emulate a config item for the recording toggle */ +static void toggle_record () +{ + bool enable = aud_get_bool ("skins", "record"); + + if (aud_drct_enable_record (enable)) + mainwin_show_status_message (enable ? _("Recording on") : _("Recording off")); + else + { + aud_set_bool ("skins", "record", aud_drct_get_record_enabled ()); + hook_call ("skins set record", nullptr); + } +} + +static void record_toggled (void * = nullptr, void * = nullptr) +{ + bool enabled = aud_drct_get_record_enabled (); + if (enabled != aud_get_bool ("skins", "record")) + { + aud_set_bool ("skins", "record", enabled); + hook_call ("skins set record", nullptr); + } +} + +static const AudguiMenuItem output_items[] = { + MenuCommand (N_("Volume Up"), "audio-volume-high", '+', NO_MOD, volume_up), + MenuCommand (N_("Volume Down"), "audio-volume-low", '-', NO_MOD, volume_down), + MenuSep (), + MenuCommand (N_("Effects ..."), nullptr, NO_KEY, configure_effects), + MenuSep (), + MenuToggle (N_("Record Stream"), nullptr, 'd', NO_MOD, "skins", "record", toggle_record, "skins set record"), + MenuCommand (N_("Audio Settings ..."), "audio-card", NO_KEY, configure_output) +}; static const AudguiMenuItem main_items[] = { MenuCommand (N_("Open Files ..."), "document-open", 'l', NO_MOD, action_play_file), @@ -67,6 +110,7 @@ static const AudguiMenuItem main_items[] = { MenuSep (), MenuSub (N_("Playback"), nullptr, get_menu_playback), MenuSub (N_("Playlist"), nullptr, get_menu_playlist), + MenuSub (N_("Output"), nullptr, {output_items}), MenuSub (N_("View"), nullptr, get_menu_view), MenuSep (), MenuSub (N_("Services"), nullptr, get_plugin_menu_main), @@ -81,6 +125,7 @@ static const AudguiMenuItem playback_items[] = { MenuSep (), MenuToggle (N_("Repeat"), nullptr, 'r', NO_MOD, nullptr, "repeat", nullptr, "set repeat"), MenuToggle (N_("Shuffle"), nullptr, 's', NO_MOD, nullptr, "shuffle", nullptr, "set shuffle"), + MenuToggle (N_("Shuffle by Album"), nullptr, NO_KEY, nullptr, "album_shuffle", nullptr, "set album_shuffle"), MenuToggle (N_("No Playlist Advance"), nullptr, 'n', CTRL, nullptr, "no_playlist_advance", nullptr, "set no_playlist_advance"), MenuToggle (N_("Stop After This Song"), nullptr, 'm', CTRL, nullptr, "stop_after_current_song", nullptr, "set stop_after_current_song"), MenuSep (), @@ -100,7 +145,7 @@ static const AudguiMenuItem playback_items[] = { static const AudguiMenuItem playlist_items[] = { MenuCommand (N_("Play/Resume"), "media-playback-start", GDK_KEY_Return, SHIFT, action_playlist_play), MenuSep (), - MenuCommand (N_("New Playlist"), "document-new", 'n', SHIFT, action_playlist_new), + MenuCommand (N_("New Playlist"), "document-new", 'n', SHIFT, (GCallback) aud_playlist_new), MenuCommand (N_("Rename Playlist ..."), "insert-text", GDK_KEY_F2, NO_MOD, action_playlist_rename), MenuCommand (N_("Remove Playlist"), "edit-delete", 'd', SHIFT, action_playlist_delete), MenuSep (), @@ -122,6 +167,7 @@ static const AudguiMenuItem view_items[] = { MenuSep (), MenuToggle (N_("Show Remaining Time"), nullptr, 'r', CTRL, "skins", "show_remaining_time", view_apply_show_remaining, "skins set show_remaining_time"), MenuSep (), + MenuToggle (N_("Double Size"), nullptr, 'd', CTRL, "skins", "double_size", view_apply_double_size, "skins set double_size"), MenuToggle (N_("Always on Top"), nullptr, 'o', CTRL, "skins", "always_on_top", view_apply_on_top, "skins set always_on_top"), MenuToggle (N_("On All Workspaces"), nullptr, 's', CTRL, "skins", "sticky", view_apply_sticky, "skins set sticky"), MenuSep (), @@ -129,7 +175,7 @@ static const AudguiMenuItem view_items[] = { MenuToggle (N_("Roll Up Playlist Editor"), nullptr, 'w', SHIFT_CTRL, "skins", "playlist_shaded", view_apply_playlist_shaded, "skins set playlist_shaded"), MenuToggle (N_("Roll Up Equalizer"), nullptr, 'w', CTRL_ALT, "skins", "equalizer_shaded", view_apply_equalizer_shaded, "skins set equalizer_shaded"), MenuSep (), - MenuToggle (N_("Double Size"), nullptr, 'd', CTRL, "skins", "double_size", view_apply_double_size, "skins set double_size") + MenuCommand (N_("_Visualizations ..."), nullptr, NO_KEY, configure_visualizations) }; static const AudguiMenuItem playlist_add_items[] = { @@ -214,28 +260,7 @@ static const AudguiMenuItem playlist_context_items[] = { MenuSub (N_("Services"), nullptr, get_plugin_menu_playlist) }; -static const AudguiMenuItem eq_preset_items[] = { - MenuCommand (N_("Load Preset ..."), "document-open", NO_KEY, eq_preset_load), - MenuCommand (N_("Load Auto Preset ..."), nullptr, NO_KEY, eq_preset_load_auto), - MenuCommand (N_("Load Default"), nullptr, NO_KEY, eq_preset_load_default), - MenuCommand (N_("Load Preset File ..."), nullptr, NO_KEY, eq_preset_load_file), - MenuCommand (N_("Load EQF File ..."), nullptr, NO_KEY, eq_preset_load_eqf), - MenuSep (), - MenuCommand (N_("Save Preset ..."), "document-save", NO_KEY, eq_preset_save), - MenuCommand (N_("Save Auto Preset ..."), nullptr, NO_KEY, eq_preset_save_auto), - MenuCommand (N_("Save Default"), nullptr, NO_KEY, eq_preset_save_default), - MenuCommand (N_("Save Preset File ..."), nullptr, NO_KEY, eq_preset_save_file), - MenuCommand (N_("Save EQF File ..."), nullptr, NO_KEY, eq_preset_save_eqf), - MenuSep (), - MenuCommand (N_("Delete Preset ..."), "edit-delete", NO_KEY, eq_preset_delete), - MenuCommand (N_("Delete Auto Preset ..."), nullptr, NO_KEY, eq_preset_delete_auto), - MenuSep (), - MenuCommand (N_("Import Winamp Presets ..."), "document-open", NO_KEY, eq_preset_import_winamp), - MenuSep (), - MenuCommand (N_("Reset to Zero"), "edit-clear", NO_KEY, eq_preset_set_zero) -}; - -void menu_init (void) +void menu_init () { static const ArrayRef<AudguiMenuItem> table[] = { {main_items}, @@ -246,10 +271,12 @@ void menu_init (void) {playlist_remove_items}, {playlist_select_items}, {playlist_sort_items}, - {playlist_context_items}, - {eq_preset_items} + {playlist_context_items} }; + record_toggled (); + hook_associate ("enable record", record_toggled, nullptr); + accel = gtk_accel_group_new (); for (int i = UI_MENUS; i --; ) @@ -260,7 +287,7 @@ void menu_init (void) } } -void menu_cleanup (void) +void menu_cleanup () { for (int i = 0; i < UI_MENUS; i ++) { @@ -270,9 +297,11 @@ void menu_cleanup (void) g_object_unref (accel); accel = nullptr; + + hook_dissociate ("enable record", record_toggled); } -GtkAccelGroup * menu_get_accel_group (void) +GtkAccelGroup * menu_get_accel_group () { return accel; } diff --git a/src/skins/menus.h b/src/skins/menus.h index bbd211a..94128ef 100644 --- a/src/skins/menus.h +++ b/src/skins/menus.h @@ -24,8 +24,7 @@ #include <gtk/gtk.h> -enum -{ +enum { UI_MENU_MAIN, UI_MENU_PLAYBACK, UI_MENU_PLAYLIST, @@ -35,14 +34,13 @@ enum UI_MENU_PLAYLIST_SELECT, UI_MENU_PLAYLIST_SORT, UI_MENU_PLAYLIST_CONTEXT, - UI_MENU_EQUALIZER_PRESET, UI_MENUS }; void menu_init (); void menu_cleanup (); -GtkAccelGroup * menu_get_accel_group (void); +GtkAccelGroup * menu_get_accel_group (); void menu_popup (int id, int x, int y, gboolean leftward, gboolean upward, int button, int time); #endif /* SKINS_MENUS_H */ diff --git a/src/skins/monostereo.cc b/src/skins/monostereo.cc new file mode 100644 index 0000000..2118e97 --- /dev/null +++ b/src/skins/monostereo.cc @@ -0,0 +1,61 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2011 John Lindgren + * + * Based on: + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include "skins_cfg.h" +#include "skin.h" +#include "monostereo.h" + +void MonoStereo::draw (cairo_t * cr) +{ + switch (m_num_channels) + { + case 0: + skin_draw_pixbuf (cr, SKIN_MONOSTEREO, 29, 12, 0, 0, 27, 12); + skin_draw_pixbuf (cr, SKIN_MONOSTEREO, 0, 12, 27, 0, 29, 12); + break; + case 1: + skin_draw_pixbuf (cr, SKIN_MONOSTEREO, 29, 0, 0, 0, 27, 12); + skin_draw_pixbuf (cr, SKIN_MONOSTEREO, 0, 12, 27, 0, 29, 12); + break; + default: + skin_draw_pixbuf (cr, SKIN_MONOSTEREO, 29, 12, 0, 0, 27, 12); + skin_draw_pixbuf (cr, SKIN_MONOSTEREO, 0, 0, 27, 0, 29, 12); + break; + } +} + +MonoStereo::MonoStereo () +{ + set_scale (config.scale); + add_drawable (56, 12); +} + +void MonoStereo::set_num_channels (int num_channels) +{ + m_num_channels = num_channels; + queue_draw (); +} diff --git a/src/skins/ui_skinned_monostereo.h b/src/skins/monostereo.h index 4cb4153..9f911cd 100644 --- a/src/skins/ui_skinned_monostereo.h +++ b/src/skins/monostereo.h @@ -28,9 +28,18 @@ #ifndef SKINS_UI_SKINNED_MONOSTEREO_H #define SKINS_UI_SKINNED_MONOSTEREO_H -#include <gtk/gtk.h> +#include "widget.h" -GtkWidget * ui_skinned_monostereo_new (void); -void ui_skinned_monostereo_set_num_channels(GtkWidget *widget, int nch); +class MonoStereo : public Widget +{ +public: + MonoStereo (); + void set_num_channels (int num_channels); + +private: + void draw (cairo_t * cr); + + int m_num_channels = 0; +}; #endif diff --git a/src/skins/number.cc b/src/skins/number.cc new file mode 100644 index 0000000..1e996cf --- /dev/null +++ b/src/skins/number.cc @@ -0,0 +1,60 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2011 John Lindgren + * + * Based on: + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include <libaudcore/runtime.h> + +#include "skins_cfg.h" +#include "main.h" +#include "skin.h" +#include "number.h" + +void SkinnedNumber::draw (cairo_t * cr) +{ + skin_draw_pixbuf (cr, SKIN_NUMBERS, m_num * 9, 0, 0, 0, 9, 13); +} + +bool SkinnedNumber::button_press (GdkEventButton * event) +{ + return change_timer_mode_cb (event); +} + +SkinnedNumber::SkinnedNumber () +{ + set_scale (config.scale); + add_input (9, 13, false, true); +} + +void SkinnedNumber::set (char c) +{ + int value = (c >= '0' && c <= '9') ? c - '0' : (c == '-') ? 11 : 10; + + if (m_num != value) + { + m_num = value; + queue_draw (); + } +} diff --git a/src/skins/number.h b/src/skins/number.h new file mode 100644 index 0000000..7c33dd5 --- /dev/null +++ b/src/skins/number.h @@ -0,0 +1,40 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2011 John Lindgren + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#ifndef SKINS_UI_SKINNED_NUMBER_H +#define SKINS_UI_SKINNED_NUMBER_H + +#include "widget.h" + +class SkinnedNumber : public Widget +{ +public: + SkinnedNumber (); + void set (char c); + +private: + virtual void draw (cairo_t * cr); + virtual bool button_press (GdkEventButton * event); + + int m_num = 0; +}; + +#endif diff --git a/src/skins/playlist-slider.cc b/src/skins/playlist-slider.cc new file mode 100644 index 0000000..a63fd40 --- /dev/null +++ b/src/skins/playlist-slider.cc @@ -0,0 +1,123 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2011 John Lindgren + * + * Based on: + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include <libaudcore/objects.h> +#include <libaudcore/playlist.h> + +#include "skins_cfg.h" +#include "skin.h" +#include "playlist-widget.h" +#include "playlist-slider.h" + +void PlaylistSlider::draw (cairo_t * cr) +{ + int rows, first; + m_list->row_info (& rows, & first); + + int range = m_length - rows; + + int y; + if (m_length > rows) + y = (first * (m_height - 19) + range / 2) / range; + else + y = 0; + + for (int i = 0; i < m_height / 29; i ++) + skin_draw_pixbuf (cr, SKIN_PLEDIT, 36, 42, 0, 29 * i, 8, 29); + + skin_draw_pixbuf (cr, SKIN_PLEDIT, m_pressed ? 61 : 52, 53, 0, y, 8, 18); +} + +void PlaylistSlider::set_pos (int y) +{ + y = aud::clamp (y, 0, m_height - 19); + + int rows, first; + m_list->row_info (& rows, & first); + + int range = m_height - 19; + m_list->scroll_to ((y * (m_length - rows) + range / 2) / range); +} + +bool PlaylistSlider::button_press (GdkEventButton * event) +{ + if (event->button != 1) + return false; + + m_pressed = true; + set_pos (event->y / config.scale - 9); + + queue_draw (); + return true; +} + +bool PlaylistSlider::button_release (GdkEventButton * event) +{ + if (event->button != 1) + return false; + + if (! m_pressed) + return true; + + m_pressed = false; + set_pos (event->y / config.scale - 9); + + queue_draw (); + return true; +} + +bool PlaylistSlider::motion (GdkEventMotion * event) +{ + if (! m_pressed) + return true; + + set_pos (event->y / config.scale - 9); + + queue_draw (); + return true; +} + +PlaylistSlider::PlaylistSlider (PlaylistWidget * list, int height) : + m_list (list), m_height (height), + m_length (aud_playlist_entry_count (aud_playlist_get_active ())) +{ + set_scale (config.scale); + add_input (8, height, true, true); +} + +void PlaylistSlider::resize (int height) +{ + m_height = height; + Widget::resize (8, height); + queue_draw (); +} + +void PlaylistSlider::refresh () +{ + m_length = aud_playlist_entry_count (aud_playlist_get_active ()); + queue_draw (); +} diff --git a/src/skins/playlist-slider.h b/src/skins/playlist-slider.h new file mode 100644 index 0000000..97c882d --- /dev/null +++ b/src/skins/playlist-slider.h @@ -0,0 +1,55 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2011 John Lindgren + * + * Based on: + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#ifndef SKINS_UI_SKINNED_PLAYLIST_SLIDER_H +#define SKINS_UI_SKINNED_PLAYLIST_SLIDER_H + +#include "widget.h" + +class PlaylistWidget; + +class PlaylistSlider : public Widget +{ +public: + PlaylistSlider (PlaylistWidget * list, int height); + void resize (int height); + void refresh (); + +private: + void draw (cairo_t * cr); + bool button_press (GdkEventButton * event); + bool button_release (GdkEventButton * event); + bool motion (GdkEventMotion * event); + + void set_pos (int y); + + PlaylistWidget * m_list; + int m_height, m_length; + bool m_pressed = false; +}; + +#endif diff --git a/src/skins/playlist-widget.cc b/src/skins/playlist-widget.cc new file mode 100644 index 0000000..d493eb6 --- /dev/null +++ b/src/skins/playlist-widget.cc @@ -0,0 +1,813 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2008 William Pitcock + * Copyright (c) 2009-2011 John Lindgren + * + * Based on: + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include <gdk/gdkkeysyms.h> + +#include "menus.h" +#include "skins_cfg.h" +#include "skin.h" +#include "playlist-widget.h" +#include "playlist-slider.h" + +#include <libaudcore/audstrings.h> +#include <libaudcore/hook.h> +#include <libaudcore/i18n.h> +#include <libaudcore/runtime.h> +#include <libaudcore/playlist.h> +#include <libaudgui/libaudgui.h> + +enum { + DRAG_SELECT = 1, + DRAG_MOVE +}; + +void PlaylistWidget::update_title () +{ + if (aud_playlist_count () > 1) + { + String title = aud_playlist_get_title (m_playlist); + m_title_text = String (str_printf (_("%s (%d of %d)"), + (const char *) title, 1 + m_playlist, aud_playlist_count ())); + } + else + m_title_text = String (); +} + +void PlaylistWidget::calc_layout () +{ + m_rows = m_height / m_row_height; + + if (m_rows && m_title_text) + { + m_offset = m_row_height; + m_rows --; + } + else + m_offset = 0; + + if (m_first + m_rows > m_length) + m_first = m_length - m_rows; + if (m_first < 0) + m_first = 0; +} + +int PlaylistWidget::calc_position (int y) const +{ + if (y < m_offset) + return -1; + + int position = m_first + (y - m_offset) / m_row_height; + if (position >= m_first + m_rows || position >= m_length) + return m_length; + + return position; +} + +int PlaylistWidget::adjust_position (bool relative, int position) const +{ + if (m_length == 0) + return -1; + + if (relative) + { + int focus = aud_playlist_get_focus (m_playlist); + if (focus == -1) + return 0; + + position += focus; + } + + if (position < 0) + return 0; + if (position >= m_length) + return m_length - 1; + + return position; +} + +void PlaylistWidget::cancel_all () +{ + m_drag = false; + + if (m_scroll) + { + m_scroll = 0; + scroll_timer.stop (); + } + + if (m_hover != -1) + { + m_hover = -1; + queue_draw (); + } + + popup_hide (); +} + +void PlaylistWidget::draw (cairo_t * cr) +{ + int active_entry = aud_playlist_get_position (m_playlist); + int left = 3, right = 3; + PangoLayout * layout; + int width; + + /* background */ + + set_cairo_color (cr, skin.colors[SKIN_PLEDIT_NORMALBG]); + cairo_paint (cr); + + /* playlist title */ + + if (m_offset) + { + layout = gtk_widget_create_pango_layout (gtk_dr (), m_title_text); + pango_layout_set_font_description (layout, m_font.get ()); + pango_layout_set_width (layout, PANGO_SCALE * (m_width - left - right)); + pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER); + pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_MIDDLE); + + cairo_move_to (cr, left, 0); + set_cairo_color (cr, skin.colors[SKIN_PLEDIT_NORMAL]); + pango_cairo_show_layout (cr, layout); + g_object_unref (layout); + } + + /* selection highlight */ + + for (int i = m_first; i < m_first + m_rows && i < m_length; i ++) + { + if (! aud_playlist_entry_get_selected (m_playlist, i)) + continue; + + cairo_rectangle (cr, 0, m_offset + m_row_height * (i - m_first), m_width, m_row_height); + set_cairo_color (cr, skin.colors[SKIN_PLEDIT_SELECTEDBG]); + cairo_fill (cr); + } + + /* entry numbers */ + + if (aud_get_bool (nullptr, "show_numbers_in_pl")) + { + width = 0; + + for (int i = m_first; i < m_first + m_rows && i < m_length; i ++) + { + char buf[16]; + snprintf (buf, sizeof buf, "%d.", 1 + i); + + layout = gtk_widget_create_pango_layout (gtk_dr (), buf); + pango_layout_set_font_description (layout, m_font.get ()); + + PangoRectangle rect; + pango_layout_get_pixel_extents (layout, nullptr, & rect); + width = aud::max (width, rect.width); + + cairo_move_to (cr, left, m_offset + m_row_height * (i - m_first)); + set_cairo_color (cr, skin.colors[(i == active_entry) ? + SKIN_PLEDIT_CURRENT : SKIN_PLEDIT_NORMAL]); + pango_cairo_show_layout (cr, layout); + g_object_unref (layout); + } + + left += width + 4; + } + + /* entry lengths */ + + width = 0; + + for (int i = m_first; i < m_first + m_rows && i < m_length; i ++) + { + Tuple tuple = aud_playlist_entry_get_tuple (m_playlist, i, Playlist::Guess); + int len = tuple.get_int (Tuple::Length); + if (len < 0) + continue; + + layout = gtk_widget_create_pango_layout (gtk_dr (), str_format_time (len)); + pango_layout_set_font_description (layout, m_font.get ()); + + PangoRectangle rect; + pango_layout_get_pixel_extents (layout, nullptr, & rect); + width = aud::max (width, rect.width); + + cairo_move_to (cr, m_width - right - rect.width, m_offset + m_row_height * (i - m_first)); + set_cairo_color (cr, skin.colors[(i == active_entry) ? + SKIN_PLEDIT_CURRENT : SKIN_PLEDIT_NORMAL]); + pango_cairo_show_layout (cr, layout); + g_object_unref (layout); + } + + right += width + 6; + + /* queue positions */ + + if (aud_playlist_queue_count (m_playlist)) + { + width = 0; + + for (int i = m_first; i < m_first + m_rows && i < m_length; i ++) + { + int pos = aud_playlist_queue_find_entry (m_playlist, i); + if (pos < 0) + continue; + + char buf[16]; + snprintf (buf, sizeof buf, "(#%d)", 1 + pos); + + layout = gtk_widget_create_pango_layout (gtk_dr (), buf); + pango_layout_set_font_description (layout, m_font.get ()); + + PangoRectangle rect; + pango_layout_get_pixel_extents (layout, nullptr, & rect); + width = aud::max (width, rect.width); + + cairo_move_to (cr, m_width - right - rect.width, m_offset + + m_row_height * (i - m_first)); + set_cairo_color (cr, skin.colors[(i == active_entry) ? + SKIN_PLEDIT_CURRENT : SKIN_PLEDIT_NORMAL]); + pango_cairo_show_layout (cr, layout); + g_object_unref (layout); + } + + right += width + 6; + } + + /* titles */ + + for (int i = m_first; i < m_first + m_rows && i < m_length; i ++) + { + Tuple tuple = aud_playlist_entry_get_tuple (m_playlist, i, Playlist::Guess); + String title = tuple.get_str (Tuple::FormattedTitle); + + layout = gtk_widget_create_pango_layout (gtk_dr (), title); + pango_layout_set_font_description (layout, m_font.get ()); + pango_layout_set_width (layout, PANGO_SCALE * (m_width - left - right)); + pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END); + + cairo_move_to (cr, left, m_offset + m_row_height * (i - m_first)); + set_cairo_color (cr, skin.colors[(i == active_entry) ? + SKIN_PLEDIT_CURRENT : SKIN_PLEDIT_NORMAL]); + pango_cairo_show_layout (cr, layout); + g_object_unref (layout); + } + + /* focus rectangle */ + + int focus = aud_playlist_get_focus (m_playlist); + + /* don't show rectangle if this is the only selected entry */ + if (focus >= m_first && focus <= m_first + m_rows - 1 && + (! aud_playlist_entry_get_selected (m_playlist, focus) || + aud_playlist_selected_count (m_playlist) > 1)) + { + cairo_new_path (cr); + cairo_set_line_width (cr, 1); + cairo_rectangle (cr, 0.5, m_offset + m_row_height * (focus - m_first) + + 0.5, m_width - 1, m_row_height - 1); + set_cairo_color (cr, skin.colors[SKIN_PLEDIT_NORMAL]); + cairo_stroke (cr); + } + + /* hover line */ + + if (m_hover >= m_first && m_hover <= m_first + m_rows) + { + cairo_new_path (cr); + cairo_set_line_width (cr, 2); + cairo_move_to (cr, 0, m_offset + m_row_height * (m_hover - m_first)); + cairo_rel_line_to (cr, m_width, 0); + set_cairo_color (cr, skin.colors[SKIN_PLEDIT_NORMAL]); + cairo_stroke (cr); + } +} + +PlaylistWidget::PlaylistWidget (int width, int height, const char * font) : + m_width (width * config.scale), + m_height (height * config.scale) +{ + add_input (m_width, m_height, true, true); + set_font (font); /* calls refresh() */ +} + +void PlaylistWidget::resize (int width, int height) +{ + m_width = width * config.scale; + m_height = height * config.scale; + + Widget::resize (m_width, m_height); + refresh (); +} + +void PlaylistWidget::set_font (const char * font) +{ + m_font.capture (pango_font_description_from_string (font)); + + PangoLayout * layout = gtk_widget_create_pango_layout (gtk_dr (), "A"); + pango_layout_set_font_description (layout, m_font.get ()); + + PangoRectangle rect; + pango_layout_get_pixel_extents (layout, nullptr, & rect); + + /* make sure row_height is non-zero; we divide by it */ + m_row_height = aud::max (rect.height, 1); + + g_object_unref (layout); + refresh (); +} + +void PlaylistWidget::refresh () +{ + m_playlist = aud_playlist_get_active (); + m_length = aud_playlist_entry_count (m_playlist); + update_title (); + calc_layout (); + + int id = aud_playlist_get_unique_id (m_playlist); + if (m_playlist_id != id) + { + cancel_all (); + m_playlist_id = id; + m_first = 0; + ensure_visible (aud_playlist_get_focus (m_playlist)); + } + + queue_draw (); + + if (m_slider) + m_slider->refresh (); +} + +void PlaylistWidget::ensure_visible (int position) +{ + if (position < m_first || position >= m_first + m_rows) + m_first = position - m_rows / 2; + + calc_layout (); +} + +void PlaylistWidget::select_single (bool relative, int position) +{ + position = adjust_position (relative, position); + + if (position == -1) + return; + + aud_playlist_select_all (m_playlist, false); + aud_playlist_entry_set_selected (m_playlist, position, true); + aud_playlist_set_focus (m_playlist, position); + ensure_visible (position); +} + +void PlaylistWidget::select_extend (bool relative, int position) +{ + position = adjust_position (relative, position); + + if (position == -1) + return; + + int count = adjust_position (true, 0); + int sign = (position > count) ? 1 : -1; + + for (; count != position; count += sign) + aud_playlist_entry_set_selected (m_playlist, count, + ! aud_playlist_entry_get_selected (m_playlist, count + sign)); + + aud_playlist_entry_set_selected (m_playlist, position, true); + aud_playlist_set_focus (m_playlist, position); + ensure_visible (position); +} + +void PlaylistWidget::select_slide (bool relative, int position) +{ + position = adjust_position (relative, position); + + if (position == -1) + return; + + aud_playlist_set_focus (m_playlist, position); + ensure_visible (position); +} + +void PlaylistWidget::select_toggle (bool relative, int position) +{ + position = adjust_position (relative, position); + + if (position == -1) + return; + + aud_playlist_entry_set_selected (m_playlist, position, + ! aud_playlist_entry_get_selected (m_playlist, position)); + aud_playlist_set_focus (m_playlist, position); + ensure_visible (position); +} + +void PlaylistWidget::select_move (bool relative, int position) +{ + int focus = aud_playlist_get_focus (m_playlist); + position = adjust_position (relative, position); + + if (focus == -1 || position == -1 || position == focus) + return; + + focus += aud_playlist_shift (m_playlist, focus, position - focus); + ensure_visible (focus); +} + +void PlaylistWidget::delete_selected () +{ + aud_playlist_delete_selected (m_playlist); + + m_length = aud_playlist_entry_count (m_playlist); + int focus = aud_playlist_get_focus (m_playlist); + + if (focus != -1) + { + aud_playlist_entry_set_selected (m_playlist, focus, true); + ensure_visible (focus); + } +} + +bool PlaylistWidget::handle_keypress (GdkEventKey * event) +{ + cancel_all (); + + switch (event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK)) + { + case 0: + switch (event->keyval) + { + case GDK_KEY_Up: + select_single (true, -1); + break; + case GDK_KEY_Down: + select_single (true, 1); + break; + case GDK_KEY_Page_Up: + select_single (true, -m_rows); + break; + case GDK_KEY_Page_Down: + select_single (true, m_rows); + break; + case GDK_KEY_Home: + select_single (false, 0); + break; + case GDK_KEY_End: + select_single (false, m_length - 1); + break; + case GDK_KEY_Return: + select_single (true, 0); + aud_playlist_set_position (m_playlist, aud_playlist_get_focus (m_playlist)); + aud_playlist_play (m_playlist); + break; + case GDK_KEY_Escape: + select_single (false, aud_playlist_get_position (m_playlist)); + break; + case GDK_KEY_Delete: + delete_selected (); + break; + default: + return false; + } + break; + case GDK_SHIFT_MASK: + switch (event->keyval) + { + case GDK_KEY_Up: + select_extend (true, -1); + break; + case GDK_KEY_Down: + select_extend (true, 1); + break; + case GDK_KEY_Page_Up: + select_extend (true, -m_rows); + break; + case GDK_KEY_Page_Down: + select_extend (true, m_rows); + break; + case GDK_KEY_Home: + select_extend (false, 0); + break; + case GDK_KEY_End: + select_extend (false, m_length - 1); + break; + default: + return false; + } + break; + case GDK_CONTROL_MASK: + switch (event->keyval) + { + case GDK_KEY_space: + select_toggle (true, 0); + break; + case GDK_KEY_Up: + select_slide (true, -1); + break; + case GDK_KEY_Down: + select_slide (true, 1); + break; + case GDK_KEY_Page_Up: + select_slide (true, -m_rows); + break; + case GDK_KEY_Page_Down: + select_slide (true, m_rows); + break; + case GDK_KEY_Home: + select_slide (false, 0); + break; + case GDK_KEY_End: + select_slide (false, m_length - 1); + break; + default: + return false; + } + break; + case GDK_MOD1_MASK: + switch (event->keyval) + { + case GDK_KEY_Up: + select_move (true, -1); + break; + case GDK_KEY_Down: + select_move (true, 1); + break; + case GDK_KEY_Page_Up: + select_move (true, -m_rows); + break; + case GDK_KEY_Page_Down: + select_move (true, m_rows); + break; + case GDK_KEY_Home: + select_move (false, 0); + break; + case GDK_KEY_End: + select_move (false, m_length - 1); + break; + default: + return false; + } + break; + default: + return false; + } + + refresh (); + return true; +} + +void PlaylistWidget::row_info (int * rows, int * first) +{ + * rows = m_rows; + * first = m_first; +} + +void PlaylistWidget::scroll_to (int row) +{ + cancel_all (); + m_first = row; + refresh (); +} + +void PlaylistWidget::set_focused (int row) +{ + cancel_all (); + aud_playlist_set_focus (m_playlist, row); + ensure_visible (row); + refresh (); +} + +void PlaylistWidget::hover (int x, int y) +{ + int row; + + if (y < m_offset) + row = m_first; + else if (y > m_offset + m_row_height * m_rows) + row = m_first + m_rows; + else + row = m_first + (y - m_offset + m_row_height / 2) / m_row_height; + + if (row > m_length) + row = m_length; + + if (row != m_hover) + { + m_hover = row; + queue_draw (); + } +} + +int PlaylistWidget::hover_end () +{ + int temp = m_hover; + m_hover = -1; + + queue_draw (); + return temp; +} + +bool PlaylistWidget::button_press (GdkEventButton * event) +{ + int position = calc_position (event->y); + int state = event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | + GDK_MOD1_MASK); + + cancel_all (); + + switch (event->type) + { + case GDK_BUTTON_PRESS: + switch (event->button) + { + case 1: + if (position == -1 || position == m_length) + return true; + + switch (state) + { + case 0: + if (aud_playlist_entry_get_selected (m_playlist, position)) + select_slide (false, position); + else + select_single (false, position); + + m_drag = DRAG_MOVE; + break; + case GDK_SHIFT_MASK: + select_extend (false, position); + m_drag = DRAG_SELECT; + break; + case GDK_CONTROL_MASK: + select_toggle (false, position); + m_drag = DRAG_SELECT; + break; + default: + return true; + } + + break; + case 3: + if (state) + return true; + + if (position != -1 && position != m_length) + { + if (aud_playlist_entry_get_selected (m_playlist, position)) + select_slide (false, position); + else + select_single (false, position); + } + + menu_popup ((position == -1) ? UI_MENU_PLAYLIST : + UI_MENU_PLAYLIST_CONTEXT, event->x_root, event->y_root, false, + false, 3, event->time); + break; + default: + return false; + } + + break; + case GDK_2BUTTON_PRESS: + if (event->button != 1 || state || position == m_length) + return true; + + if (position != -1) + aud_playlist_set_position (m_playlist, position); + + aud_playlist_play (m_playlist); + break; + default: + return true; + } + + refresh (); + return true; +} + +bool PlaylistWidget::button_release (GdkEventButton * event) +{ + cancel_all (); + return true; +} + +void PlaylistWidget::scroll_timeout () +{ + int position = adjust_position (true, m_scroll); + if (position == -1) + return; + + switch (m_drag) + { + case DRAG_SELECT: + select_extend (false, position); + break; + case DRAG_MOVE: + select_move (false, position); + break; + } + + refresh (); +} + +bool PlaylistWidget::motion (GdkEventMotion * event) +{ + int position = calc_position (event->y); + + if (m_drag) + { + if (position == -1 || position == m_length) + { + if (! m_scroll) + scroll_timer.start (); + + m_scroll = (position == -1 ? -1 : 1); + } + else + { + if (m_scroll) + { + m_scroll = 0; + scroll_timer.stop (); + } + + switch (m_drag) + { + case DRAG_SELECT: + select_extend (false, position); + break; + case DRAG_MOVE: + select_move (false, position); + break; + } + + refresh (); + } + } + else + { + if (position == -1 || position == m_length) + cancel_all (); + else if (aud_get_bool (nullptr, "show_filepopup_for_tuple") && m_popup_pos != position) + { + cancel_all (); + popup_trigger (position); + } + } + + return true; +} + +bool PlaylistWidget::leave () +{ + if (! m_drag) + cancel_all (); + + return true; +} + +void PlaylistWidget::popup_trigger (int pos) +{ + audgui_infopopup_hide (); + + auto show_cb = [] (void * me_) { + auto me = (PlaylistWidget *) me_; + audgui_infopopup_show (me->m_playlist, me->m_popup_pos); + }; + + m_popup_pos = pos; + m_popup_timer.queue (aud_get_int (nullptr, "filepopup_delay") * 100, show_cb, this); +} + +void PlaylistWidget::popup_hide () +{ + audgui_infopopup_hide (); + + m_popup_pos = -1; + m_popup_timer.stop (); +} diff --git a/src/skins/playlist-widget.h b/src/skins/playlist-widget.h new file mode 100644 index 0000000..deb5f3a --- /dev/null +++ b/src/skins/playlist-widget.h @@ -0,0 +1,97 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2009-2011 John Lindgren + * + * Based on: + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#ifndef SKINS_UI_SKINNED_PLAYLIST_H +#define SKINS_UI_SKINNED_PLAYLIST_H + +#include <libaudcore/hook.h> +#include <libaudcore/mainloop.h> +#include <libaudcore/objects.h> + +#include "widget.h" + +class PlaylistSlider; + +typedef SmartPtr<PangoFontDescription, pango_font_description_free> PangoFontDescPtr; + +class PlaylistWidget : public Widget +{ +public: + PlaylistWidget (int width, int height, const char * font); + ~PlaylistWidget () { cancel_all (); } + + void set_slider (PlaylistSlider * slider) { m_slider = slider; } + void resize (int width, int height); + void set_font (const char * m_font); + void refresh (); + bool handle_keypress (GdkEventKey * event); + void row_info (int * m_rows, int * m_first); + void scroll_to (int row); + void set_focused (int row); + void hover (int x, int y); + int hover_end (); + +private: + void draw (cairo_t * cr); + bool button_press (GdkEventButton * event); + bool button_release (GdkEventButton * event); + bool motion (GdkEventMotion * event); + bool leave (); + + void update_title (); + void calc_layout (); + + int calc_position (int y) const; + int adjust_position (bool relative, int position) const; + + void ensure_visible (int position); + void select_single (bool relative, int position); + void select_extend (bool relative, int position); + void select_slide (bool relative, int position); + void select_toggle (bool relative, int position); + void select_move (bool relative, int position); + void delete_selected (); + + void cancel_all (); + void scroll_timeout (); + void popup_trigger (int pos); + void popup_hide (); + + const Timer<PlaylistWidget> + scroll_timer {TimerRate::Hz10, this, & PlaylistWidget::scroll_timeout}; + + PlaylistSlider * m_slider = nullptr; + PangoFontDescPtr m_font; + String m_title_text; + + int m_playlist = -1, m_playlist_id = -1, m_length = 0; + int m_width = 0, m_height = 0, m_row_height = 1, m_offset = 0, m_rows = 0, m_first = 0; + int m_scroll = 0, m_hover = -1, m_drag = 0, m_popup_pos = -1; + QueuedFunc m_popup_timer; +}; + +#endif diff --git a/src/skins/playlist.cc b/src/skins/playlist.cc new file mode 100644 index 0000000..0ab4a42 --- /dev/null +++ b/src/skins/playlist.cc @@ -0,0 +1,551 @@ +/* Audacious - Cross-platform multimedia player + * Copyright (C) 2005-2011 Audacious development team. + * + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include <inttypes.h> +#include <string.h> + +#include <gdk/gdkkeysyms.h> +#include <gtk/gtk.h> + +#include <libaudcore/audstrings.h> +#include <libaudcore/drct.h> +#include <libaudcore/hook.h> +#include <libaudcore/i18n.h> +#include <libaudcore/playlist.h> +#include <libaudcore/runtime.h> +#include <libaudcore/tuple.h> +#include <libaudgui/libaudgui.h> + +#include "actions-mainwin.h" +#include "dnd.h" +#include "drag-handle.h" +#include "menus.h" +#include "plugin.h" +#include "skins_cfg.h" +#include "main.h" +#include "playlist.h" +#include "button.h" +#include "playlist-widget.h" +#include "playlist-slider.h" +#include "textbox.h" +#include "window.h" +#include "view.h" + +#define PLAYLISTWIN_MIN_WIDTH MAINWIN_WIDTH +#define PLAYLISTWIN_MIN_HEIGHT MAINWIN_HEIGHT +#define PLAYLISTWIN_WIDTH_SNAP 25 +#define PLAYLISTWIN_HEIGHT_SNAP 29 +#define PLAYLISTWIN_SHADED_HEIGHT MAINWIN_SHADED_HEIGHT + +#define APPEND(b, ...) snprintf (b + strlen (b), sizeof b - strlen (b), __VA_ARGS__) + +class PlWindow : public Window +{ +public: + PlWindow (bool shaded) : + Window (WINDOW_PLAYLIST, & config.playlist_x, & config.playlist_y, + config.playlist_width, shaded ? PLAYLISTWIN_SHADED_HEIGHT : + config.playlist_height, shaded) {} + +private: + void draw (cairo_t * cr); + bool button_press (GdkEventButton * event); + bool scroll (GdkEventScroll * event); +}; + +Window * playlistwin; +PlaylistWidget * playlistwin_list; +TextBox * playlistwin_sinfo; + +static Button * playlistwin_shade, * playlistwin_close; +static Button * playlistwin_shaded_shade, * playlistwin_shaded_close; + +static PlaylistSlider * playlistwin_slider; +static TextBox * playlistwin_time_min, * playlistwin_time_sec; +static TextBox * playlistwin_info; +static Button * playlistwin_srew, * playlistwin_splay; +static Button * playlistwin_spause, * playlistwin_sstop; +static Button * playlistwin_sfwd, * playlistwin_seject; +static Button * playlistwin_sscroll_up, *playlistwin_sscroll_down; +static DragHandle * resize_handle, * sresize_handle; +static Button * button_add, * button_sub, * button_sel, * button_misc, * button_list; + +static int resize_base_width, resize_base_height; +static int drop_position; +static bool song_changed; + +static void update_info () +{ + int playlist = aud_playlist_get_active (); + StringBuf s1 = str_format_time (aud_playlist_get_selected_length (playlist)); + StringBuf s2 = str_format_time (aud_playlist_get_total_length (playlist)); + playlistwin_info->set_text (str_concat ({s1, "/", s2})); +} + +static void update_rollup_text () +{ + int playlist = aud_playlist_get_active (); + int entry = aud_playlist_get_position (playlist); + Tuple tuple = aud_playlist_entry_get_tuple (playlist, entry, Playlist::Guess); + char scratch[512]; + + scratch[0] = 0; + + if (entry > -1) + { + String title = tuple.get_str (Tuple::FormattedTitle); + int length = tuple.get_int (Tuple::Length); + + if (aud_get_bool (nullptr, "show_numbers_in_pl")) + APPEND (scratch, "%d. ", 1 + entry); + + APPEND (scratch, "%s", (const char *) title); + + if (length >= 0) + { + StringBuf buf = str_format_time (length); + APPEND (scratch, " (%s)", (const char *) buf); + } + } + + playlistwin_sinfo->set_text (scratch); +} + +static void playlistwin_shade_toggle () +{ + view_set_playlist_shaded (! aud_get_bool ("skins", "playlist_shaded")); +} + +static void playlistwin_scroll (int dir) +{ + int rows, first; + + playlistwin_list->row_info (& rows, & first); + playlistwin_list->scroll_to (first + dir * rows / 3); +} + +static void playlistwin_scroll_up_pushed () +{ + playlistwin_scroll (-1); +} + +static void playlistwin_scroll_down_pushed () +{ + playlistwin_scroll (1); +} + +/* note: height is ignored if the window is shaded */ +static void playlistwin_resize (int w, int h) +{ + int tx, ty; + + tx = (w - PLAYLISTWIN_MIN_WIDTH) / PLAYLISTWIN_WIDTH_SNAP; + tx = (tx * PLAYLISTWIN_WIDTH_SNAP) + PLAYLISTWIN_MIN_WIDTH; + if (tx < PLAYLISTWIN_MIN_WIDTH) + tx = PLAYLISTWIN_MIN_WIDTH; + + if (! aud_get_bool ("skins", "playlist_shaded")) + { + ty = (h - PLAYLISTWIN_MIN_HEIGHT) / PLAYLISTWIN_HEIGHT_SNAP; + ty = (ty * PLAYLISTWIN_HEIGHT_SNAP) + PLAYLISTWIN_MIN_HEIGHT; + if (ty < PLAYLISTWIN_MIN_HEIGHT) + ty = PLAYLISTWIN_MIN_HEIGHT; + } + else + ty = config.playlist_height; + + if (tx == config.playlist_width && ty == config.playlist_height) + return; + + config.playlist_width = w = tx; + config.playlist_height = h = ty; + + playlistwin_list->resize (w - 31, h - 58); + playlistwin->move_widget (false, playlistwin_slider, w - 15, 20); + playlistwin_slider->resize (h - 58); + + playlistwin->move_widget (true, playlistwin_shaded_shade, w - 21, 3); + playlistwin->move_widget (true, playlistwin_shaded_close, w - 11, 3); + playlistwin->move_widget (false, playlistwin_shade, w - 21, 3); + playlistwin->move_widget (false, playlistwin_close, w - 11, 3); + + playlistwin->move_widget (false, playlistwin_time_min, w - 82, h - 15); + playlistwin->move_widget (false, playlistwin_time_sec, w - 64, h - 15); + playlistwin->move_widget (false, playlistwin_info, w - 143, h - 28); + + playlistwin->move_widget (false, playlistwin_srew, w - 144, h - 16); + playlistwin->move_widget (false, playlistwin_splay, w - 138, h - 16); + playlistwin->move_widget (false, playlistwin_spause, w - 128, h - 16); + playlistwin->move_widget (false, playlistwin_sstop, w - 118, h - 16); + playlistwin->move_widget (false, playlistwin_sfwd, w - 109, h - 16); + playlistwin->move_widget (false, playlistwin_seject, w - 100, h - 16); + playlistwin->move_widget (false, playlistwin_sscroll_up, w - 14, h - 35); + playlistwin->move_widget (false, playlistwin_sscroll_down, w - 14, h - 30); + + playlistwin->move_widget (false, resize_handle, w - 20, h - 20); + playlistwin->move_widget (true, sresize_handle, w - 31, 0); + + playlistwin_sinfo->set_width (w - 35); + + playlistwin->move_widget (false, button_add, 12, h - 29); + playlistwin->move_widget (false, button_sub, 40, h - 29); + playlistwin->move_widget (false, button_sel, 68, h - 29); + playlistwin->move_widget (false, button_misc, 100, h - 29); + playlistwin->move_widget (false, button_list, w - 46, h - 29); +} + +bool PlWindow::scroll (GdkEventScroll * event) +{ + switch (event->direction) + { + case GDK_SCROLL_DOWN: + playlistwin_scroll (1); + break; + case GDK_SCROLL_UP: + playlistwin_scroll (-1); + break; + default: + break; + } + + return true; +} + +bool PlWindow::button_press (GdkEventButton * event) +{ + if (event->button == 1 && event->type == GDK_2BUTTON_PRESS && + event->window == gtk_widget_get_window (gtk ()) && event->y < 14) + { + playlistwin_shade_toggle (); + return true; + } + + if (event->button == 3 && event->type == GDK_BUTTON_PRESS) + { + menu_popup (UI_MENU_PLAYLIST, event->x_root, event->y_root, false, false, 3, event->time); + return true; + } + + return Window::button_press (event); +} + +void playlistwin_hide_timer () +{ + playlistwin_time_min->set_text (nullptr); + playlistwin_time_sec->set_text (nullptr); +} + +void playlistwin_set_time (const char * minutes, const char * seconds) +{ + playlistwin_time_min->set_text (minutes); + playlistwin_time_sec->set_text (seconds); +} + +static void drag_motion (GtkWidget * widget, GdkDragContext * context, int x, + int y, unsigned time, void * unused) +{ + if (! aud_get_bool ("skins", "playlist_shaded")) + playlistwin_list->hover (x - 12, y - 20); +} + +static void drag_leave (GtkWidget * widget, GdkDragContext * context, unsigned time, + void * unused) +{ + if (! aud_get_bool ("skins", "playlist_shaded")) + playlistwin_list->hover_end (); +} + +static void drag_drop (GtkWidget * widget, GdkDragContext * context, int x, + int y, unsigned time, void * unused) +{ + if (aud_get_bool ("skins", "playlist_shaded")) + drop_position = -1; + else + { + playlistwin_list->hover (x - 12, y - 20); + drop_position = playlistwin_list->hover_end (); + } +} + +static void drag_data_received (GtkWidget * widget, GdkDragContext * context, + int x, int y, GtkSelectionData * data, unsigned info, unsigned time, void * unused) +{ + audgui_urilist_insert (aud_playlist_get_active (), drop_position, + (const char *) gtk_selection_data_get_data (data)); + drop_position = -1; +} + +static void playlistwin_hide () +{ + view_set_show_playlist (false); +} + +static void resize_press () +{ + resize_base_width = config.playlist_width; + resize_base_height = config.playlist_height; +} + +static void resize_drag (int x_offset, int y_offset) +{ + bool shaded = aud_get_bool ("skins", "playlist_shaded"); + + /* compromise between rounding and truncating; this has no real + * justification at all other than it "looks about right". */ + playlistwin_resize (resize_base_width + x_offset + PLAYLISTWIN_WIDTH_SNAP / + 3, resize_base_height + y_offset + PLAYLISTWIN_HEIGHT_SNAP / 3); + playlistwin->resize (config.playlist_width, shaded ? + PLAYLISTWIN_SHADED_HEIGHT : config.playlist_height); +} + +static void button_add_cb (Button * button, GdkEventButton * event) +{ + int xpos, ypos; + playlistwin->getPosition (& xpos, & ypos); + menu_popup (UI_MENU_PLAYLIST_ADD, xpos + 12 * config.scale, + ypos + (config.playlist_height - 8) * config.scale, false, true, + event->button, event->time); +} + +static void button_sub_cb (Button * button, GdkEventButton * event) +{ + int xpos, ypos; + playlistwin->getPosition (& xpos, & ypos); + menu_popup (UI_MENU_PLAYLIST_REMOVE, xpos + 40 * config.scale, + ypos + (config.playlist_height - 8) * config.scale, false, true, + event->button, event->time); +} + +static void button_sel_cb (Button * button, GdkEventButton * event) +{ + int xpos, ypos; + playlistwin->getPosition (& xpos, & ypos); + menu_popup (UI_MENU_PLAYLIST_SELECT, xpos + 68 * config.scale, + ypos + (config.playlist_height - 8) * config.scale, false, true, + event->button, event->time); +} + +static void button_misc_cb (Button * button, GdkEventButton * event) +{ + int xpos, ypos; + playlistwin->getPosition (& xpos, & ypos); + menu_popup (UI_MENU_PLAYLIST_SORT, xpos + 100 * config.scale, + ypos + (config.playlist_height - 8) * config.scale, false, true, + event->button, event->time); +} + +static void button_list_cb (Button * button, GdkEventButton * event) +{ + int xpos, ypos; + playlistwin->getPosition (& xpos, & ypos); + menu_popup (UI_MENU_PLAYLIST, + xpos + (config.playlist_width - 12) * config.scale, + ypos + (config.playlist_height - 8) * config.scale, true, true, + event->button, event->time); +} + +static void playlistwin_create_widgets () +{ + int w = config.playlist_width, h = config.playlist_height; + + bool shaded = aud_get_bool ("skins", "playlist_shaded"); + playlistwin_sinfo = new TextBox (w - 35, nullptr, shaded && config.autoscroll); + playlistwin->put_widget (true, playlistwin_sinfo, 4, 4); + + playlistwin_shaded_shade = new Button (9, 9, 128, 45, 150, 42, SKIN_PLEDIT, SKIN_PLEDIT); + playlistwin->put_widget (true, playlistwin_shaded_shade, w - 21, 3); + playlistwin_shaded_shade->on_release ((ButtonCB) playlistwin_shade_toggle); + + playlistwin_shaded_close = new Button (9, 9, 138, 45, 52, 42, SKIN_PLEDIT, SKIN_PLEDIT); + playlistwin->put_widget (true, playlistwin_shaded_close, w - 11, 3); + playlistwin_shaded_close->on_release ((ButtonCB) playlistwin_hide); + + playlistwin_shade = new Button (9, 9, 157, 3, 62, 42, SKIN_PLEDIT, SKIN_PLEDIT); + playlistwin->put_widget (false, playlistwin_shade, w - 21, 3); + playlistwin_shade->on_release ((ButtonCB) playlistwin_shade_toggle); + + playlistwin_close = new Button (9, 9, 167, 3, 52, 42, SKIN_PLEDIT, SKIN_PLEDIT); + playlistwin->put_widget (false, playlistwin_close, w - 11, 3); + playlistwin_close->on_release ((ButtonCB) playlistwin_hide); + + String font = aud_get_str ("skins", "playlist_font"); + playlistwin_list = new PlaylistWidget (w - 31, h - 58, font); + playlistwin->put_widget (false, playlistwin_list, 12, 20); + + /* playlist list box slider */ + playlistwin_slider = new PlaylistSlider (playlistwin_list, h - 58); + playlistwin->put_widget (false, playlistwin_slider, w - 15, 20); + playlistwin_list->set_slider (playlistwin_slider); + + playlistwin_time_min = new TextBox (15, nullptr, false); + playlistwin->put_widget (false, playlistwin_time_min, w - 82, h - 15); + playlistwin_time_min->on_press (change_timer_mode_cb); + + playlistwin_time_sec = new TextBox (10, nullptr, false); + playlistwin->put_widget (false, playlistwin_time_sec, w - 64, h - 15); + playlistwin_time_sec->on_press (change_timer_mode_cb); + + playlistwin_info = new TextBox (90, nullptr, false); + playlistwin->put_widget (false, playlistwin_info, w - 143, h - 28); + + /* mini play control buttons at right bottom corner */ + + playlistwin_srew = new Button (8, 7); + playlistwin->put_widget (false, playlistwin_srew, w - 144, h - 16); + playlistwin_srew->on_release ((ButtonCB) aud_drct_pl_prev); + + playlistwin_splay = new Button (10, 7); + playlistwin->put_widget (false, playlistwin_splay, w - 138, h - 16); + playlistwin_splay->on_release ((ButtonCB) aud_drct_play); + + playlistwin_spause = new Button (10, 7); + playlistwin->put_widget (false, playlistwin_spause, w - 128, h - 16); + playlistwin_spause->on_release ((ButtonCB) aud_drct_pause); + + playlistwin_sstop = new Button (9, 7); + playlistwin->put_widget (false, playlistwin_sstop, w - 118, h - 16); + playlistwin_sstop->on_release ((ButtonCB) aud_drct_stop); + + playlistwin_sfwd = new Button (8, 7); + playlistwin->put_widget (false, playlistwin_sfwd, w - 109, h - 16); + playlistwin_sfwd->on_release ((ButtonCB) aud_drct_pl_next); + + playlistwin_seject = new Button (9, 7); + playlistwin->put_widget (false, playlistwin_seject, w - 100, h - 16); + playlistwin_seject->on_release ((ButtonCB) action_play_file); + + playlistwin_sscroll_up = new Button (8, 5); + playlistwin->put_widget (false, playlistwin_sscroll_up, w - 14, h - 35); + playlistwin_sscroll_up->on_release ((ButtonCB) playlistwin_scroll_up_pushed); + + playlistwin_sscroll_down = new Button (8, 5); + playlistwin->put_widget (false, playlistwin_sscroll_down, w - 14, h - 30); + playlistwin_sscroll_down->on_release ((ButtonCB) playlistwin_scroll_down_pushed); + + /* resize handles */ + + resize_handle = new DragHandle (20, 20, resize_press, resize_drag); + playlistwin->put_widget (false, resize_handle, w - 20, h - 20); + + sresize_handle = new DragHandle (9, PLAYLISTWIN_SHADED_HEIGHT, resize_press, resize_drag); + playlistwin->put_widget (true, sresize_handle, w - 31, 0); + + /* lower button row */ + + button_add = new Button (25, 18); + playlistwin->put_widget (false, button_add, 12, h - 29); + button_add->on_press (button_add_cb); + + button_sub = new Button (25, 18); + playlistwin->put_widget (false, button_sub, 40, h - 29); + button_sub->on_press (button_sub_cb); + + button_sel = new Button (25, 18); + playlistwin->put_widget (false, button_sel, 68, h - 29); + button_sel->on_press (button_sel_cb); + + button_misc = new Button (25, 18); + playlistwin->put_widget (false, button_misc, 100, h - 29); + button_misc->on_press (button_misc_cb); + + button_list = new Button (23, 18); + playlistwin->put_widget (false, button_list, w - 46, h - 29); + button_list->on_press (button_list_cb); +} + +void PlWindow::draw (cairo_t * cr) +{ + if (is_shaded ()) + skin_draw_playlistwin_shaded (cr, config.playlist_width, true); + else + skin_draw_playlistwin_frame (cr, config.playlist_width, + config.playlist_height, true); +} + +static void playlistwin_create_window () +{ + bool shaded = aud_get_bool ("skins", "playlist_shaded"); + + playlistwin = new PlWindow (shaded); + playlistwin->setWindowTitle (_("Audacious Playlist Editor")); + + GtkWidget * w = playlistwin->gtk (); + drag_dest_set (w); + drop_position = -1; + + g_signal_connect (w, "drag-motion", (GCallback) drag_motion, nullptr); + g_signal_connect (w, "drag-leave", (GCallback) drag_leave, nullptr); + g_signal_connect (w, "drag-drop", (GCallback) drag_drop, nullptr); + g_signal_connect (w, "drag-data-received", (GCallback) drag_data_received, nullptr); +} + +static void update_cb (void *, void *) +{ + playlistwin_list->refresh (); + + if (song_changed) + { + playlistwin_list->set_focused (aud_playlist_get_position (aud_playlist_get_active ())); + song_changed = false; + } + + update_info (); + update_rollup_text (); +} + +static void follow_cb (void * data, void *) +{ + int list = aud::from_ptr<int> (data); + aud_playlist_select_all (list, false); + + int row = aud_playlist_get_position (list); + if (row >= 0) + aud_playlist_entry_set_selected (list, row, true); + + if (list == aud_playlist_get_active ()) + song_changed = true; +} + +void playlistwin_create () +{ + playlistwin_create_window (); + playlistwin_create_widgets (); + + update_info (); + update_rollup_text (); + + song_changed = false; + + hook_associate ("playlist position", follow_cb, nullptr); + hook_associate ("playlist activate", update_cb, nullptr); + hook_associate ("playlist update", update_cb, nullptr); +} + +void playlistwin_unhook () +{ + hook_dissociate ("playlist position", follow_cb); + hook_dissociate ("playlist activate", update_cb); + hook_dissociate ("playlist update", update_cb); +} diff --git a/src/skins/playlist.h b/src/skins/playlist.h new file mode 100644 index 0000000..3f224a2 --- /dev/null +++ b/src/skins/playlist.h @@ -0,0 +1,39 @@ +/* BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#ifndef SKINS_UI_PLAYLIST_H +#define SKINS_UI_PLAYLIST_H + +class PlaylistWidget; +class TextBox; +class Window; + +void playlistwin_create (); +void playlistwin_unhook (); +void playlistwin_hide_timer (); +void playlistwin_set_time (const char * minutes, const char * seconds); + +extern Window * playlistwin; +extern PlaylistWidget * playlistwin_list; +extern TextBox * playlistwin_sinfo; + +#endif /* SKINS_UI_PLAYLIST_H */ diff --git a/src/skins/ui_skinned_horizontal_slider.h b/src/skins/playstatus.cc index 8668856..85c192d 100644 --- a/src/skins/ui_skinned_horizontal_slider.h +++ b/src/skins/playstatus.cc @@ -25,21 +25,39 @@ * Audacious or using our public API to be a derived work. */ -#ifndef SKINS_UI_SKINNED_HORIZONTAL_SLIDER_H -#define SKINS_UI_SKINNED_HORIZONTAL_SLIDER_H +#include "skins_cfg.h" +#include "skin.h" +#include "playstatus.h" -#include <gtk/gtk.h> +void PlayStatus::draw (cairo_t * cr) +{ + if (m_status == STATUS_PLAY) + skin_draw_pixbuf (cr, SKIN_PLAYPAUSE, 36, 0, 0, 0, 3, 9); + else + skin_draw_pixbuf (cr, SKIN_PLAYPAUSE, 27, 0, 0, 0, 2, 9); -GtkWidget * hslider_new (int min, int max, SkinPixmapId si, int w, int h, - int fx, int fy, int kw, int kh, int knx, int kny, int kpx, int kpy); -void hslider_set_frame (GtkWidget * hslider, int fx, int fy); -void hslider_set_knob (GtkWidget * hslider, int knx, int kny, int kpx, int - kpy); -int hslider_get_pos (GtkWidget * hslider); -void hslider_set_pos (GtkWidget * hslider, int pos); -gboolean hslider_get_pressed (GtkWidget * hslider); -void hslider_set_pressed (GtkWidget * hslider, gboolean pressed); -void hslider_on_motion (GtkWidget * hslider, void (* callback) (void)); -void hslider_on_release (GtkWidget * hslider, void (* callback) (void)); + switch (m_status) + { + case STATUS_STOP: + skin_draw_pixbuf (cr, SKIN_PLAYPAUSE, 18, 0, 2, 0, 9, 9); + break; + case STATUS_PAUSE: + skin_draw_pixbuf (cr, SKIN_PLAYPAUSE, 9, 0, 2, 0, 9, 9); + break; + case STATUS_PLAY: + skin_draw_pixbuf (cr, SKIN_PLAYPAUSE, 1, 0, 3, 0, 8, 9); + break; + } +} -#endif +PlayStatus::PlayStatus () +{ + set_scale (config.scale); + add_drawable (11, 9); +} + +void PlayStatus::set_status (PStatus status) +{ + m_status = status; + queue_draw (); +} diff --git a/src/skins/playstatus.h b/src/skins/playstatus.h new file mode 100644 index 0000000..3213759 --- /dev/null +++ b/src/skins/playstatus.h @@ -0,0 +1,51 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2011 John Lindgren + * + * Based on: + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#ifndef SKINS_UI_SKINNED_PLAYSTATUS_H +#define SKINS_UI_SKINNED_PLAYSTATUS_H + +#include "widget.h" + +typedef enum { + STATUS_STOP, + STATUS_PAUSE, + STATUS_PLAY +} PStatus; + +class PlayStatus : public Widget +{ +public: + PlayStatus (); + void set_status (PStatus status); + +private: + void draw (cairo_t * cr); + + PStatus m_status = STATUS_STOP; +}; + +#endif diff --git a/src/skins/plugin-window.cc b/src/skins/plugin-window.cc index afb4b00..d438abf 100644 --- a/src/skins/plugin-window.cc +++ b/src/skins/plugin-window.cc @@ -32,6 +32,10 @@ #include <libaudcore/plugins.h> #include <libaudcore/hook.h> #include <libaudcore/runtime.h> +#include <libaudgui/libaudgui-gtk.h> + +#include "main.h" +#include "window.h" static GList * windows; @@ -58,6 +62,8 @@ static void add_dock_plugin (PluginHandle * plugin, void * unused) { GtkWidget * window = gtk_window_new (GTK_WINDOW_TOPLEVEL); gtk_window_set_title ((GtkWindow *) window, aud_plugin_get_name (plugin)); + gtk_window_set_transient_for ((GtkWindow *) window, (GtkWindow *) mainwin->gtk ()); + gtk_container_set_border_width ((GtkContainer *) window, 2); gtk_container_add ((GtkContainer *) window, widget); g_object_set_data ((GObject *) window, "skins-plugin-id", plugin); @@ -76,7 +82,10 @@ static void add_dock_plugin (PluginHandle * plugin, void * unused) gtk_window_move ((GtkWindow *) window, pos[0], pos[1]); } else - gtk_window_set_default_size ((GtkWindow *) window, 300, 200); + { + int dpi = audgui_get_dpi (); + gtk_window_set_default_size ((GtkWindow *) window, 3 * dpi, 2 * dpi); + } if (aud_ui_is_shown ()) gtk_widget_show_all (window); @@ -116,7 +125,7 @@ static void remove_dock_plugin (PluginHandle * plugin, void * unused) } } -void create_plugin_windows (void) +void create_plugin_windows () { for (PluginHandle * plugin : aud_plugin_list (PluginType::General)) { @@ -134,7 +143,7 @@ void create_plugin_windows (void) hook_associate ("dock plugin disabled", (HookFunction) remove_dock_plugin, nullptr); } -void show_plugin_windows (void) +void show_plugin_windows () { g_list_foreach (windows, (GFunc) gtk_widget_show_all, nullptr); } @@ -148,13 +157,13 @@ void focus_plugin_window (PluginHandle * plugin) aud_plugin_send_message (plugin, "grab focus", nullptr, 0); } -void hide_plugin_windows (void) +void hide_plugin_windows () { g_list_foreach (windows, (GFunc) save_window_size, nullptr); g_list_foreach (windows, (GFunc) gtk_widget_hide, nullptr); } -void destroy_plugin_windows (void) +void destroy_plugin_windows () { for (PluginHandle * plugin : aud_plugin_list (PluginType::General)) { diff --git a/src/skins/plugin-window.h b/src/skins/plugin-window.h index 3359893..68a2ac2 100644 --- a/src/skins/plugin-window.h +++ b/src/skins/plugin-window.h @@ -24,10 +24,10 @@ class PluginHandle; -void create_plugin_windows (void); -void show_plugin_windows (void); +void create_plugin_windows (); +void show_plugin_windows (); void focus_plugin_window (PluginHandle * plugin); -void hide_plugin_windows (void); -void destroy_plugin_windows (void); +void hide_plugin_windows (); +void destroy_plugin_windows (); #endif /* SKINS_PLUGIN_WINDOW_H */ diff --git a/src/skins/plugin.cc b/src/skins/plugin.cc index fc7f60c..a027615 100644 --- a/src/skins/plugin.cc +++ b/src/skins/plugin.cc @@ -20,6 +20,8 @@ #include <stdlib.h> +#define AUD_PLUGIN_GLIB_ONLY +#include <libaudcore/audstrings.h> #include <libaudcore/drct.h> #include <libaudcore/i18n.h> #include <libaudcore/interface.h> @@ -27,18 +29,18 @@ #include <libaudcore/plugin.h> #include <libaudcore/hook.h> #include <libaudgui/libaudgui.h> +#include <libaudgui/libaudgui-gtk.h> #include "menus.h" #include "plugin.h" #include "plugin-window.h" -#include "preset-browser.h" -#include "preset-list.h" #include "skins_cfg.h" -#include "ui_equalizer.h" -#include "ui_main.h" -#include "ui_main_evlisteners.h" -#include "ui_playlist.h" -#include "ui_skin.h" +#include "equalizer.h" +#include "main.h" +#include "vis-callbacks.h" +#include "playlist.h" +#include "skin.h" +#include "window.h" #include "view.h" class SkinnedUI : public IfacePlugin @@ -88,83 +90,96 @@ public: EXPORT SkinnedUI aud_plugin_instance; -char * skins_paths[SKINS_PATH_COUNT]; +static String user_skin_dir; +static String skin_thumb_dir; -static int update_source; - -static void skins_free_paths(void) { - int i; +const char * skins_get_user_skin_dir () +{ + if (! user_skin_dir) + user_skin_dir = String (filename_build ({g_get_user_data_dir (), "audacious", "Skins"})); - for (i = 0; i < SKINS_PATH_COUNT; i++) { - g_free(skins_paths[i]); - skins_paths[i] = nullptr; - } + return user_skin_dir; } -static void skins_init_paths () +const char * skins_get_skin_thumb_dir () { - const char * xdg_data_home = g_get_user_data_dir (); - const char * xdg_cache_home = g_get_user_cache_dir (); + if (! skin_thumb_dir) + skin_thumb_dir = String (filename_build ({g_get_user_cache_dir (), "audacious", "thumbs-unscaled"})); - skins_paths[SKINS_PATH_USER_SKIN_DIR] = - g_build_filename(xdg_data_home, "audacious", "Skins", nullptr); - skins_paths[SKINS_PATH_SKIN_THUMB_DIR] = - g_build_filename(xdg_cache_home, "audacious", "thumbs", nullptr); + return skin_thumb_dir; } -static gboolean update_cb (void *) +static bool load_initial_skin () { - mainwin_update_song_info (); - return G_SOURCE_CONTINUE; + String path = aud_get_str ("skins", "skin"); + if (path[0] && skin_load (path)) + return true; + + StringBuf def = filename_build ({aud_get_path (AudPath::DataDir), "Skins", "Default"}); + if (skin_load (def)) + return true; + + AUDERR ("Unable to load any skin; giving up!\n"); + return false; } -static void skins_init_main (void) +static void skins_init_main (bool restart) { - init_skins (aud_get_str ("skins", "skin")); + int old_scale = config.scale; + // The current scaling implementation allows any integer scale factor, but + // the legacy "double size" config option is limited to two choices. For + // now, the two options are floor(DPI/96) and floor(DPI/96)+1. On screens + // up to 191 DPI, this gives the traditional 1x and 2x scale factors. + config.scale = aud::max (1, audgui_get_dpi () / 96) + + aud_get_bool ("skins", "double_size"); + + if (restart && config.scale != old_scale) + dock_change_scale (old_scale, config.scale); + + mainwin_create (); + equalizerwin_create (); + playlistwin_create (); + + view_apply_skin (); view_apply_on_top (); view_apply_sticky (); if (aud_drct_get_playing ()) - { - ui_main_evlistener_playback_begin (nullptr, nullptr); - if (aud_drct_get_paused ()) - ui_main_evlistener_playback_pause (nullptr, nullptr); - } + mainwin_playback_begin (); else mainwin_update_song_info (); - update_source = g_timeout_add (250, update_cb, nullptr); + timer_add (TimerRate::Hz4, (TimerFunc) mainwin_update_song_info); } bool SkinnedUI::init () { - if (aud_get_mainloop_type () != MainloopType::GLib) + skins_cfg_load (); + + if (! load_initial_skin ()) return false; audgui_init (); - - skins_cfg_load (); - skins_init_paths (); - menu_init (); - skins_init_main (); + skins_init_main (false); create_plugin_windows (); return true; } -static void skins_cleanup_main (void) +static void skins_cleanup_main () { mainwin_unhook (); + equalizerwin_unhook (); playlistwin_unhook (); - g_source_remove (update_source); - cleanup_skins (); + timer_remove (TimerRate::Hz4, (TimerFunc) mainwin_update_song_info); - eq_preset_browser_cleanup (); - eq_preset_list_cleanup (); + gtk_widget_destroy (mainwin->gtk ()); mainwin = nullptr; + gtk_widget_destroy (playlistwin->gtk ()); playlistwin = nullptr; + gtk_widget_destroy (equalizerwin->gtk ()); equalizerwin = nullptr; } void SkinnedUI::cleanup () @@ -175,28 +190,28 @@ void SkinnedUI::cleanup () skins_cleanup_main (); menu_cleanup (); + audgui_cleanup (); - skins_free_paths (); + skin = Skin (); - audgui_cleanup (); + user_skin_dir = String (); + skin_thumb_dir = String (); } -void skins_restart (void) +void skins_restart () { skins_cleanup_main (); - skins_init_main (); + skins_init_main (true); if (aud_ui_is_shown ()) view_show_player (true); } -gboolean handle_window_close (void) +void skins_close () { - gboolean handled = FALSE; + bool handled = false; hook_call ("window close", & handled); if (! handled) aud_quit (); - - return TRUE; } diff --git a/src/skins/plugin.h b/src/skins/plugin.h index 9f94c83..174b4aa 100644 --- a/src/skins/plugin.h +++ b/src/skins/plugin.h @@ -21,18 +21,10 @@ #ifndef PLUGIN_SKINS_H #define PLUGIN_SKINS_H -#include <glib.h> +const char * skins_get_user_skin_dir (); +const char * skins_get_skin_thumb_dir (); -enum { - SKINS_PATH_USER_SKIN_DIR, - SKINS_PATH_SKIN_THUMB_DIR, - SKINS_PATH_COUNT -}; - -extern char * skins_paths[]; - -void skins_restart (void); - -gboolean handle_window_close (void); +void skins_restart (); +void skins_close (); #endif diff --git a/src/skins/preset-browser.cc b/src/skins/preset-browser.cc deleted file mode 100644 index 538b95e..0000000 --- a/src/skins/preset-browser.cc +++ /dev/null @@ -1,158 +0,0 @@ -/* - * preset-browser.c - * Copyright 2014 John Lindgren - * - * This file is part of Audacious. - * - * Audacious 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, version 2 or version 3 of the License. - * - * Audacious 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 - * Audacious. If not, see <http://www.gnu.org/licenses/>. - * - * The Audacious team does not consider modular code linking to Audacious or - * using our public API to be a derived work. - */ - -#include "preset-browser.h" - -#include <gtk/gtk.h> - -#include <libaudcore/audstrings.h> -#include <libaudcore/drct.h> -#include <libaudcore/i18n.h> -#include <libaudcore/vfs.h> - -#include "ui_equalizer.h" - -typedef void (* FilebrowserCallback) (const char * filename); - -static GtkWidget * preset_browser; - -static void browser_response (GtkWidget * dialog, int response, void * data) -{ - if (response == GTK_RESPONSE_ACCEPT) - { - char * filename = gtk_file_chooser_get_uri ((GtkFileChooser *) dialog); - ((FilebrowserCallback) data) (filename); - g_free (filename); - } - - gtk_widget_destroy (dialog); -} - -static void show_preset_browser (const char * title, gboolean save, - const char * default_filename, FilebrowserCallback callback) -{ - if (preset_browser) - gtk_widget_destroy (preset_browser); - - preset_browser = gtk_file_chooser_dialog_new (title, nullptr, save ? - GTK_FILE_CHOOSER_ACTION_SAVE : GTK_FILE_CHOOSER_ACTION_OPEN, _("Cancel"), - GTK_RESPONSE_CANCEL, save ? _("Save") : _("Load"), GTK_RESPONSE_ACCEPT, - nullptr); - - if (default_filename) - gtk_file_chooser_set_current_name ((GtkFileChooser *) preset_browser, default_filename); - - g_signal_connect (preset_browser, "response", (GCallback) browser_response, (void *) callback); - g_signal_connect (preset_browser, "destroy", (GCallback) - gtk_widget_destroyed, & preset_browser); - - gtk_window_present ((GtkWindow *) preset_browser); -} - -static void do_load_file (const char * filename) -{ - EqualizerPreset preset; - - VFSFile file (filename, "r"); - if (! file || ! aud_load_preset_file (preset, file)) - return; - - equalizerwin_apply_preset (preset); -} - -void eq_preset_load_file (void) -{ - show_preset_browser (_("Load Preset File"), FALSE, nullptr, do_load_file); -} - -static void do_load_eqf (const char * filename) -{ - VFSFile file (filename, "r"); - if (! file) - return; - - Index<EqualizerPreset> presets = aud_import_winamp_presets (file); - - if (presets.len ()) - equalizerwin_apply_preset (presets[0]); -} - -void eq_preset_load_eqf (void) -{ - show_preset_browser (_("Load EQF File"), FALSE, nullptr, do_load_eqf); -} - -static void do_save_file (const char * filename) -{ - EqualizerPreset preset; - equalizerwin_update_preset (preset); - - VFSFile file (filename, "w"); - if (file) - aud_save_preset_file (preset, file); -} - -void eq_preset_save_file (void) -{ - String title = aud_drct_get_title (); - StringBuf name = title ? str_printf ("%s.%s", (const char *) title, - EQUALIZER_DEFAULT_PRESET_EXT) : StringBuf (); - - show_preset_browser (_("Save Preset File"), TRUE, name, do_save_file); -} - -static void do_save_eqf (const char * filename) -{ - VFSFile file (filename, "w"); - if (! file) - return; - - EqualizerPreset preset = EqualizerPreset (); - preset.name = String ("Preset1"); - - equalizerwin_update_preset (preset); - aud_export_winamp_preset (preset, file); -} - -void eq_preset_save_eqf (void) -{ - show_preset_browser (_("Save EQF File"), TRUE, nullptr, do_save_eqf); -} - -static void do_import_winamp (const char * filename) -{ - VFSFile file (filename, "r"); - if (! file) - return; - - equalizerwin_import_presets (aud_import_winamp_presets (file)); -} - -void eq_preset_import_winamp (void) -{ - show_preset_browser (_("Import Winamp Presets"), FALSE, nullptr, do_import_winamp); -} - -void eq_preset_browser_cleanup (void) -{ - if (preset_browser) - gtk_widget_destroy (preset_browser); -} diff --git a/src/skins/preset-list.cc b/src/skins/preset-list.cc deleted file mode 100644 index 1b60264..0000000 --- a/src/skins/preset-list.cc +++ /dev/null @@ -1,462 +0,0 @@ -/* Audacious - Cross-platform multimedia player - * Copyright (C) 2005-2014 Audacious development team. - * - * Based on BMP: - * Copyright (C) 2003-2004 BMP development team. - * - * Based on XMMS: - * Copyright (C) 1998-2003 XMMS development team. - * - * 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; under version 3 of the License. - * - * 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 <http://www.gnu.org/licenses>. - * - * The Audacious team does not consider modular code linking to - * Audacious or using our public API to be a derived work. - */ - -#include "preset-list.h" - -#include <string.h> -#include <gtk/gtk.h> - -#include <libaudcore/drct.h> -#include <libaudcore/i18n.h> -#include <libaudgui/libaudgui-gtk.h> - -#include "ui_equalizer.h" - -static GtkWidget *equalizerwin_load_window = nullptr; -static GtkWidget *equalizerwin_load_auto_window = nullptr; -static GtkWidget *equalizerwin_save_window = nullptr; -static GtkWidget *equalizerwin_save_entry = nullptr; -static GtkWidget *equalizerwin_save_auto_window = nullptr; -static GtkWidget *equalizerwin_save_auto_entry = nullptr; -static GtkWidget *equalizerwin_delete_window = nullptr; -static GtkWidget *equalizerwin_delete_auto_window = nullptr; - -static void -equalizerwin_delete_selected_presets(GtkTreeView *view, const char *filename) -{ - char *text; - - GtkTreeSelection *selection = gtk_tree_view_get_selection(view); - GtkTreeModel *model = gtk_tree_view_get_model(view); - - /* - * first we are making a list of the selected rows, then we convert this - * list into a list of GtkTreeRowReferences, so that when you delete an - * item you can still access the other items - * finally we iterate through all GtkTreeRowReferences, convert them to - * GtkTreeIters and delete those one after the other - */ - - GList *list = gtk_tree_selection_get_selected_rows(selection, &model); - GList *rrefs = nullptr; - GList *litr; - - for (litr = list; litr; litr = litr->next) - { - GtkTreePath *path = (GtkTreePath *) litr->data; - rrefs = g_list_append(rrefs, gtk_tree_row_reference_new(model, path)); - } - - for (litr = rrefs; litr; litr = litr->next) - { - GtkTreeRowReference *ref = (GtkTreeRowReference *) litr->data; - GtkTreePath *path = gtk_tree_row_reference_get_path(ref); - GtkTreeIter iter; - gtk_tree_model_get_iter(model, &iter, path); - gtk_tree_path_free(path); - - gtk_tree_model_get(model, &iter, 0, &text, -1); - - if (!strcmp(filename, "eq.preset")) - equalizerwin_delete_preset (equalizer_presets, text, filename); - else if (!strcmp(filename, "eq.auto_preset")) - equalizerwin_delete_preset (equalizer_auto_presets, text, filename); - - gtk_list_store_remove(GTK_LIST_STORE(model), &iter); - } -} - -static void -equalizerwin_save_ok(GtkWidget * widget, void * data) -{ - const char *text; - - text = gtk_entry_get_text(GTK_ENTRY(equalizerwin_save_entry)); - - if (text[0]) - equalizerwin_save_preset (equalizer_presets, text, "eq.preset"); - - gtk_widget_destroy(equalizerwin_save_window); -} - -static void -equalizerwin_save_select(GtkTreeView *treeview, GtkTreePath *path, - GtkTreeViewColumn *col, void * data) -{ - char *text; - - GtkTreeSelection *selection = gtk_tree_view_get_selection(treeview); - GtkTreeModel *model; - GtkTreeIter iter; - - if (selection) - { - if (gtk_tree_selection_get_selected(selection, &model, &iter)) - { - gtk_tree_model_get(model, &iter, 0, &text, -1); - gtk_entry_set_text(GTK_ENTRY(equalizerwin_save_entry), text); - equalizerwin_save_ok(nullptr, nullptr); - - g_free(text); - } - } -} - -static void -equalizerwin_load_ok(GtkWidget *widget, void * data) -{ - char *text; - - GtkTreeView* view = GTK_TREE_VIEW(data); - GtkTreeSelection *selection = gtk_tree_view_get_selection(view); - GtkTreeModel *model; - GtkTreeIter iter; - - if (selection) - { - if (gtk_tree_selection_get_selected(selection, &model, &iter)) - { - gtk_tree_model_get(model, &iter, 0, &text, -1); - equalizerwin_load_preset(equalizer_presets, text); - - g_free(text); - } - } - gtk_widget_destroy(equalizerwin_load_window); -} - -static void -equalizerwin_load_select(GtkTreeView *treeview, GtkTreePath *path, - GtkTreeViewColumn *col, void * data) -{ - equalizerwin_load_ok(nullptr, treeview); -} - -static void -equalizerwin_delete_delete(GtkWidget *widget, void * data) -{ - equalizerwin_delete_selected_presets(GTK_TREE_VIEW(data), "eq.preset"); -} - -static void -equalizerwin_save_auto_ok(GtkWidget *widget, void * data) -{ - const char *text; - - text = gtk_entry_get_text(GTK_ENTRY(equalizerwin_save_auto_entry)); - - if (text[0]) - equalizerwin_save_preset (equalizer_auto_presets, text, "eq.auto_preset"); - - gtk_widget_destroy(equalizerwin_save_auto_window); -} - -static void -equalizerwin_save_auto_select(GtkTreeView *treeview, GtkTreePath *path, - GtkTreeViewColumn *col, void * data) -{ - char *text; - - GtkTreeSelection *selection = gtk_tree_view_get_selection(treeview); - GtkTreeModel *model; - GtkTreeIter iter; - - if (selection) - { - if (gtk_tree_selection_get_selected(selection, &model, &iter)) - { - gtk_tree_model_get(model, &iter, 0, &text, -1); - gtk_entry_set_text(GTK_ENTRY(equalizerwin_save_auto_entry), text); - equalizerwin_save_auto_ok(nullptr, nullptr); - - g_free(text); - } - } -} - -static void -equalizerwin_load_auto_ok(GtkWidget *widget, void * data) -{ - char *text; - - GtkTreeView *view = GTK_TREE_VIEW(data); - GtkTreeSelection *selection = gtk_tree_view_get_selection(view); - GtkTreeModel *model; - GtkTreeIter iter; - - if (selection) - { - if (gtk_tree_selection_get_selected(selection, &model, &iter)) - { - gtk_tree_model_get(model, &iter, 0, &text, -1); - equalizerwin_load_preset(equalizer_auto_presets, text); - - g_free(text); - } - } - gtk_widget_destroy(equalizerwin_load_auto_window); -} - -static void -equalizerwin_load_auto_select(GtkTreeView *treeview, GtkTreePath *path, - GtkTreeViewColumn *col, void * data) -{ - equalizerwin_load_auto_ok(nullptr, treeview); -} - -static void -equalizerwin_delete_auto_delete(GtkWidget *widget, void * data) -{ - equalizerwin_delete_selected_presets(GTK_TREE_VIEW(data), "eq.auto_preset"); -} - -static GtkWidget * equalizerwin_create_list_window - (const Index<EqualizerPreset> & preset_list, const char * title, - GtkWidget * * window, GtkSelectionMode sel_mode, GtkWidget * * entry, - GtkWidget * button_action, GCallback action_func, GCallback select_row_func) -{ - GtkWidget *vbox, *scrolled_window, *bbox, *view; - GtkWidget *button_cancel; - - GtkListStore *store; - GtkTreeIter iter; - GtkTreeModel *model; - GtkCellRenderer *renderer; - GtkTreeSelection *selection; - GtkTreeSortable *sortable; - - *window = gtk_window_new(GTK_WINDOW_TOPLEVEL); - gtk_window_set_title(GTK_WINDOW(*window), title); - gtk_window_set_type_hint(GTK_WINDOW(*window), GDK_WINDOW_TYPE_HINT_DIALOG); - gtk_window_set_default_size(GTK_WINDOW(*window), 350, 300); - gtk_container_set_border_width(GTK_CONTAINER(*window), 10); - gtk_window_set_transient_for(GTK_WINDOW(*window), - GTK_WINDOW(equalizerwin)); - g_signal_connect(*window, "destroy", - G_CALLBACK(gtk_widget_destroyed), window); - - audgui_destroy_on_escape (* window); - - vbox = gtk_vbox_new (FALSE, 10); - gtk_container_add(GTK_CONTAINER(*window), vbox); - - scrolled_window = gtk_scrolled_window_new(nullptr, nullptr); - gtk_scrolled_window_set_shadow_type ((GtkScrolledWindow *) scrolled_window, GTK_SHADOW_IN); - gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scrolled_window), - GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS); - - /* fill the store with the names of all available presets */ - store = gtk_list_store_new(1, G_TYPE_STRING); - for (const EqualizerPreset & preset : preset_list) - { - gtk_list_store_append (store, & iter); - gtk_list_store_set (store, & iter, 0, (const char *) preset.name, -1); - } - model = GTK_TREE_MODEL(store); - - sortable = GTK_TREE_SORTABLE(store); - gtk_tree_sortable_set_sort_column_id(sortable, 0, GTK_SORT_ASCENDING); - - view = gtk_tree_view_new(); - renderer = gtk_cell_renderer_text_new(); - gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), -1, - _("Presets"), renderer, - "text", 0, nullptr); - gtk_tree_view_set_model(GTK_TREE_VIEW(view), model); - g_object_unref(model); - - selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(view)); - gtk_tree_selection_set_mode(selection, sel_mode); - - gtk_container_add(GTK_CONTAINER(scrolled_window), view); - gtk_box_pack_start(GTK_BOX(vbox), scrolled_window, TRUE, TRUE, 0); - - if (entry) { - *entry = gtk_entry_new(); - g_signal_connect(*entry, "activate", action_func, nullptr); - gtk_box_pack_start(GTK_BOX(vbox), *entry, FALSE, FALSE, 0); - } - - bbox = gtk_hbutton_box_new(); - gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); - gtk_box_set_spacing(GTK_BOX(bbox), 5); - gtk_box_pack_start(GTK_BOX(vbox), bbox, FALSE, FALSE, 0); - - button_cancel = audgui_button_new (_("Cancel"), "process-stop", nullptr, nullptr); - g_signal_connect_swapped (button_cancel, "clicked", (GCallback) - gtk_widget_destroy, * window); - gtk_box_pack_start(GTK_BOX(bbox), button_cancel, TRUE, TRUE, 0); - - g_signal_connect(button_action, "clicked", G_CALLBACK(action_func), view); - gtk_widget_set_can_default (button_action, TRUE); - - if (select_row_func) - g_signal_connect(view, "row-activated", G_CALLBACK(select_row_func), nullptr); - - gtk_box_pack_start(GTK_BOX(bbox), button_action, TRUE, TRUE, 0); - - gtk_widget_grab_default(button_action); - - gtk_widget_show_all(*window); - - return *window; -} - -void eq_preset_load (void) -{ - if (equalizerwin_load_window) { - gtk_window_present(GTK_WINDOW(equalizerwin_load_window)); - return; - } - - equalizerwin_create_list_window(equalizer_presets, - _("Load preset"), - &equalizerwin_load_window, - GTK_SELECTION_SINGLE, nullptr, - audgui_button_new (_("Load"), "document-open", nullptr, nullptr), - G_CALLBACK(equalizerwin_load_ok), - G_CALLBACK(equalizerwin_load_select)); -} - -void eq_preset_load_auto (void) -{ - if (equalizerwin_load_auto_window) { - gtk_window_present(GTK_WINDOW(equalizerwin_load_auto_window)); - return; - } - - equalizerwin_create_list_window(equalizer_auto_presets, - _("Load auto-preset"), - &equalizerwin_load_auto_window, - GTK_SELECTION_SINGLE, nullptr, - audgui_button_new (_("Load"), "document-open", nullptr, nullptr), - G_CALLBACK(equalizerwin_load_auto_ok), - G_CALLBACK(equalizerwin_load_auto_select)); -} - -void eq_preset_save (void) -{ - if (equalizerwin_save_window) { - gtk_window_present(GTK_WINDOW(equalizerwin_save_window)); - return; - } - - equalizerwin_create_list_window(equalizer_presets, - _("Save preset"), - &equalizerwin_save_window, - GTK_SELECTION_SINGLE, - &equalizerwin_save_entry, - audgui_button_new (_("Save"), "document-save", nullptr, nullptr), - G_CALLBACK(equalizerwin_save_ok), - G_CALLBACK(equalizerwin_save_select)); -} - -void eq_preset_save_auto (void) -{ - if (equalizerwin_save_auto_window) - gtk_window_present(GTK_WINDOW(equalizerwin_save_auto_window)); - else - equalizerwin_create_list_window(equalizer_auto_presets, - _("Save auto-preset"), - &equalizerwin_save_auto_window, - GTK_SELECTION_SINGLE, - &equalizerwin_save_auto_entry, - audgui_button_new (_("Save"), "document-save", nullptr, nullptr), - G_CALLBACK(equalizerwin_save_auto_ok), - G_CALLBACK(equalizerwin_save_auto_select)); - - String name = aud_drct_get_filename (); - - if (name != nullptr) - { - char * base = g_path_get_basename (name); - gtk_entry_set_text ((GtkEntry *) equalizerwin_save_auto_entry, base); - g_free (base); - } -} - -void eq_preset_delete (void) -{ - if (equalizerwin_delete_window) { - gtk_window_present(GTK_WINDOW(equalizerwin_delete_window)); - return; - } - - equalizerwin_create_list_window(equalizer_presets, - _("Delete preset"), - &equalizerwin_delete_window, - GTK_SELECTION_MULTIPLE, nullptr, - audgui_button_new (_("Delete"), "edit-delete", nullptr, nullptr), - G_CALLBACK(equalizerwin_delete_delete), - nullptr); -} - -void eq_preset_delete_auto (void) -{ - if (equalizerwin_delete_auto_window) { - gtk_window_present(GTK_WINDOW(equalizerwin_delete_auto_window)); - return; - } - - equalizerwin_create_list_window(equalizer_auto_presets, - _("Delete auto-preset"), - &equalizerwin_delete_auto_window, - GTK_SELECTION_MULTIPLE, nullptr, - audgui_button_new (_("Delete"), "edit-delete", nullptr, nullptr), - G_CALLBACK(equalizerwin_delete_auto_delete), - nullptr); -} - -void eq_preset_load_default (void) -{ - if (! equalizerwin_load_preset (equalizer_presets, _("Default"))) - eq_preset_set_zero (); -} - -void eq_preset_save_default (void) -{ - equalizerwin_save_preset (equalizer_presets, _("Default"), "eq.preset"); -} - -void eq_preset_set_zero (void) -{ - equalizerwin_apply_preset (EqualizerPreset ()); -} - -void eq_preset_list_cleanup (void) -{ - if (equalizerwin_load_window) - gtk_widget_destroy (equalizerwin_load_window); - if (equalizerwin_load_auto_window) - gtk_widget_destroy (equalizerwin_load_auto_window); - if (equalizerwin_save_window) - gtk_widget_destroy (equalizerwin_save_window); - if (equalizerwin_save_auto_window) - gtk_widget_destroy (equalizerwin_save_auto_window); - if (equalizerwin_delete_window) - gtk_widget_destroy (equalizerwin_delete_window); - if (equalizerwin_delete_auto_window) - gtk_widget_destroy (equalizerwin_delete_auto_window); -} diff --git a/src/skins/search-select.cc b/src/skins/search-select.cc new file mode 100644 index 0000000..47741c1 --- /dev/null +++ b/src/skins/search-select.cc @@ -0,0 +1,204 @@ +/* Audacious - Cross-platform multimedia player + * Copyright (C) 2005-2011 Audacious development team. + * + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include "actions-playlist.h" +#include "playlist.h" +#include "playlist-widget.h" + +#include <gdk/gdkkeysyms.h> +#include <gtk/gtk.h> + +#include <libaudcore/i18n.h> +#include <libaudcore/playlist.h> +#include <libaudcore/runtime.h> + +static void search_cbt_cb (GtkWidget * called_cbt, GtkWidget * other_cbt) +{ + if (gtk_toggle_button_get_active ((GtkToggleButton *) called_cbt)) + gtk_toggle_button_set_active ((GtkToggleButton *) other_cbt, false); +} + +static gboolean search_kp_cb (GtkWidget * entry, GdkEventKey * event, GtkWidget * dialog) +{ + if (event->keyval != GDK_KEY_Return) + return false; + + gtk_dialog_response ((GtkDialog *) dialog, GTK_RESPONSE_ACCEPT); + return true; +} + +static void copy_selected_to_new (int playlist) +{ + int entries = aud_playlist_entry_count (playlist); + Index<PlaylistAddItem> items; + + for (int entry = 0; entry < entries; entry ++) + { + if (aud_playlist_entry_get_selected (playlist, entry)) + { + items.append + (aud_playlist_entry_get_filename (playlist, entry), + aud_playlist_entry_get_tuple (playlist, entry, Playlist::Nothing)); + } + } + + int new_list = aud_playlist_new (); + aud_playlist_entry_insert_batch (new_list, 0, std::move (items), false); +} + +void action_playlist_search_and_select () +{ + /* create dialog */ + GtkWidget * dialog = gtk_dialog_new_with_buttons ( + _("Search entries in active playlist"), nullptr, (GtkDialogFlags) 0 , + _("Cancel"), GTK_RESPONSE_REJECT, _("Search"), GTK_RESPONSE_ACCEPT, nullptr); + + /* help text and logo */ + GtkWidget * hbox = gtk_hbox_new (false, 6); + GtkWidget * logo = gtk_image_new_from_icon_name ("edit-find", GTK_ICON_SIZE_DIALOG); + GtkWidget * helptext = gtk_label_new (_("Select entries in playlist by filling one or more " + "fields. Fields use regular expressions syntax, case-insensitive. If you don't know how " + "regular expressions work, simply insert a literal portion of what you're searching for.")); + gtk_label_set_line_wrap ((GtkLabel *) helptext, true); + gtk_box_pack_start ((GtkBox *) hbox, logo, false, false, 0); + gtk_box_pack_start ((GtkBox *) hbox, helptext, false, false, 0); + + /* title */ + GtkWidget * label_title = gtk_label_new (_("Title:")); + gtk_misc_set_alignment ((GtkMisc *) label_title, 1, 0.5); + GtkWidget * entry_title = gtk_entry_new (); + g_signal_connect (entry_title, "key-press-event", (GCallback) search_kp_cb, dialog); + + /* album */ + GtkWidget * label_album = gtk_label_new (_("Album:")); + gtk_misc_set_alignment ((GtkMisc *) label_album, 1, 0.5); + GtkWidget * entry_album = gtk_entry_new (); + g_signal_connect (entry_album, "key-press-event", (GCallback) search_kp_cb, dialog); + + /* artist */ + GtkWidget * label_performer = gtk_label_new (_("Artist:")); + gtk_misc_set_alignment ((GtkMisc *) label_performer, 1, 0.5); + GtkWidget * entry_performer = gtk_entry_new (); + g_signal_connect (entry_performer, "key-press-event", (GCallback) search_kp_cb, dialog); + + /* file name */ + GtkWidget * label_file_name = gtk_label_new (_("File Name:")); + gtk_misc_set_alignment ((GtkMisc *) label_file_name, 1, 0.5); + GtkWidget * entry_file_name = gtk_entry_new (); + g_signal_connect (entry_file_name, "key-press-event", + (GCallback) search_kp_cb, dialog); + + /* some options that control behaviour */ + GtkWidget * checkbt_clearprevsel = gtk_check_button_new_with_label ( + _("Clear previous selection before searching")); + gtk_toggle_button_set_active ((GtkToggleButton *) checkbt_clearprevsel, true); + GtkWidget * checkbt_autoenqueue = gtk_check_button_new_with_label ( + _("Automatically toggle queue for matching entries")); + gtk_toggle_button_set_active ((GtkToggleButton *) checkbt_autoenqueue, false); + GtkWidget * checkbt_newplaylist = gtk_check_button_new_with_label ( + _("Create a new playlist with matching entries")); + gtk_toggle_button_set_active ((GtkToggleButton *) checkbt_newplaylist, false); + + g_signal_connect (checkbt_autoenqueue, "clicked", + (GCallback) search_cbt_cb, checkbt_newplaylist); + g_signal_connect (checkbt_newplaylist, "clicked", + (GCallback) search_cbt_cb, checkbt_autoenqueue); + + /* place fields in grid */ + GtkTable * grid = (GtkTable *) gtk_table_new (0, 0, false); + gtk_table_set_row_spacings (grid, 6); + gtk_table_set_col_spacings (grid, 6); + gtk_table_attach_defaults (grid, hbox, 0, 2, 0, 1); + gtk_table_attach (grid, label_title, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 0, 0); + gtk_table_attach_defaults (grid, entry_title, 1, 2, 1, 2); + gtk_table_attach (grid, label_album, 0, 1, 2, 3, GTK_FILL, GTK_FILL, 0, 0); + gtk_table_attach_defaults (grid, entry_album, 1, 2, 2, 3); + gtk_table_attach (grid, label_performer, 0, 1, 3, 4, GTK_FILL, GTK_FILL, 0, 0); + gtk_table_attach_defaults (grid, entry_performer, 1, 2, 3, 4); + gtk_table_attach (grid, label_file_name, 0, 1, 4, 5, GTK_FILL, GTK_FILL, 0, 0); + gtk_table_attach_defaults (grid, entry_file_name, 1, 2, 4, 5); + gtk_table_attach_defaults (grid, checkbt_clearprevsel, 0, 2, 5, 6); + gtk_table_attach_defaults (grid, checkbt_autoenqueue, 0, 2, 6, 7); + gtk_table_attach_defaults (grid, checkbt_newplaylist, 0, 2, 7, 8); + + gtk_container_set_border_width ((GtkContainer *) grid, 5); + gtk_container_add ((GtkContainer *) gtk_dialog_get_content_area + ((GtkDialog *) dialog), (GtkWidget *) grid); + gtk_widget_show_all (dialog); + + if (gtk_dialog_run ((GtkDialog *) dialog) == GTK_RESPONSE_ACCEPT) + { + /* create a TitleInput tuple with user search data */ + Tuple tuple; + const char * searchdata = nullptr; + int active_playlist = aud_playlist_get_active (); + + searchdata = gtk_entry_get_text ((GtkEntry *) entry_title); + AUDDBG ("title=\"%s\"\n", searchdata); + tuple.set_str (Tuple::Title, searchdata); + + searchdata = gtk_entry_get_text ((GtkEntry *) entry_album); + AUDDBG ("album=\"%s\"\n", searchdata); + tuple.set_str (Tuple::Album, searchdata); + + searchdata = gtk_entry_get_text ((GtkEntry *) entry_performer); + AUDDBG ("performer=\"%s\"\n", searchdata); + tuple.set_str (Tuple::Artist, searchdata); + + searchdata = gtk_entry_get_text ((GtkEntry *) entry_file_name); + AUDDBG ("filename=\"%s\"\n", searchdata); + tuple.set_str (Tuple::Basename, searchdata); + + /* check if previous selection should be cleared before searching */ + if (gtk_toggle_button_get_active ((GtkToggleButton *) checkbt_clearprevsel)) + aud_playlist_select_all (active_playlist, false); + + aud_playlist_select_by_patterns (active_playlist, tuple); + + /* check if a new playlist should be created after searching */ + if (gtk_toggle_button_get_active ((GtkToggleButton *) checkbt_newplaylist)) + copy_selected_to_new (active_playlist); + else + { + /* set focus on the first entry found */ + int entries = aud_playlist_entry_count (active_playlist); + for (int count = 0; count < entries; count ++) + { + if (aud_playlist_entry_get_selected (active_playlist, count)) + { + playlistwin_list->set_focused (count); + break; + } + } + + /* check if matched entries should be queued */ + if (gtk_toggle_button_get_active ((GtkToggleButton *) checkbt_autoenqueue)) + aud_playlist_queue_insert_selected (active_playlist, -1); + } + } + + /* done here :) */ + gtk_widget_destroy (dialog); +} diff --git a/src/skins/skin-ini.cc b/src/skins/skin-ini.cc new file mode 100644 index 0000000..3c6d052 --- /dev/null +++ b/src/skins/skin-ini.cc @@ -0,0 +1,278 @@ +/* + * Audacious + * Copyright 2011-2013 Audacious development team + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include <stdlib.h> +#include <glib.h> + +#include <libaudcore/inifile.h> + +#include "skins_cfg.h" +#include "skin.h" +#include "util.h" + +/* + * skin.hints parsing + */ + +typedef struct { + const char * name; + int * value_ptr; +} HintPair; + +/* in alphabetical order to allow binary search */ +static const HintPair hint_pairs[] = { + {"mainwinaboutx", & skin.hints.mainwin_about_x}, + {"mainwinabouty", & skin.hints.mainwin_about_y}, + {"mainwinbalancex", & skin.hints.mainwin_balance_x}, + {"mainwinbalancey", & skin.hints.mainwin_balance_y}, + {"mainwinclosex", & skin.hints.mainwin_close_x}, + {"mainwinclosey", & skin.hints.mainwin_close_y}, + {"mainwinejectx", & skin.hints.mainwin_eject_x}, + {"mainwinejecty", & skin.hints.mainwin_eject_y}, + {"mainwineqbuttonx", & skin.hints.mainwin_eqbutton_x}, + {"mainwineqbuttony", & skin.hints.mainwin_eqbutton_y}, + {"mainwinheight", & skin.hints.mainwin_height}, + {"mainwininfobarx", & skin.hints.mainwin_infobar_x}, + {"mainwininfobary", & skin.hints.mainwin_infobar_y}, + {"mainwinmenurowvisible", & skin.hints.mainwin_menurow_visible}, + {"mainwinminimizex", & skin.hints.mainwin_minimize_x}, + {"mainwinminimizey", & skin.hints.mainwin_minimize_y}, + {"mainwinnextx", & skin.hints.mainwin_next_x}, + {"mainwinnexty", & skin.hints.mainwin_next_y}, + {"mainwinnumber0x", & skin.hints.mainwin_number_0_x}, + {"mainwinnumber0y", & skin.hints.mainwin_number_0_y}, + {"mainwinnumber1x", & skin.hints.mainwin_number_1_x}, + {"mainwinnumber1y", & skin.hints.mainwin_number_1_y}, + {"mainwinnumber2x", & skin.hints.mainwin_number_2_x}, + {"mainwinnumber2y", & skin.hints.mainwin_number_2_y}, + {"mainwinnumber3x", & skin.hints.mainwin_number_3_x}, + {"mainwinnumber3y", & skin.hints.mainwin_number_3_y}, + {"mainwinnumber4x", & skin.hints.mainwin_number_4_x}, + {"mainwinnumber4y", & skin.hints.mainwin_number_4_y}, + {"mainwinothertextisstatus", & skin.hints.mainwin_othertext_is_status}, + {"mainwinothertextvisible", & skin.hints.mainwin_othertext_visible}, + {"mainwinpausex", & skin.hints.mainwin_pause_x}, + {"mainwinpausey", & skin.hints.mainwin_pause_y}, + {"mainwinplaystatusx", & skin.hints.mainwin_playstatus_x}, + {"mainwinplaystatusy", & skin.hints.mainwin_playstatus_y}, + {"mainwinplayx", & skin.hints.mainwin_play_x}, + {"mainwinplayy", & skin.hints.mainwin_play_y}, + {"mainwinplbuttonx", & skin.hints.mainwin_plbutton_x}, + {"mainwinplbuttony", & skin.hints.mainwin_plbutton_y}, + {"mainwinpositionx", & skin.hints.mainwin_position_x}, + {"mainwinpositiony", & skin.hints.mainwin_position_y}, + {"mainwinpreviousx", & skin.hints.mainwin_previous_x}, + {"mainwinpreviousy", & skin.hints.mainwin_previous_y}, + {"mainwinrepeatx", & skin.hints.mainwin_repeat_x}, + {"mainwinrepeaty", & skin.hints.mainwin_repeat_y}, + {"mainwinshadex", & skin.hints.mainwin_shade_x}, + {"mainwinshadey", & skin.hints.mainwin_shade_y}, + {"mainwinshufflex", & skin.hints.mainwin_shuffle_x}, + {"mainwinshuffley", & skin.hints.mainwin_shuffle_y}, + {"mainwinstopx", & skin.hints.mainwin_stop_x}, + {"mainwinstopy", & skin.hints.mainwin_stop_y}, + {"mainwinstreaminfovisible", & skin.hints.mainwin_streaminfo_visible}, + {"mainwintextvisible", & skin.hints.mainwin_text_visible}, + {"mainwintextwidth", & skin.hints.mainwin_text_width}, + {"mainwintextx", & skin.hints.mainwin_text_x}, + {"mainwintexty", & skin.hints.mainwin_text_y}, + {"mainwinvisvisible", & skin.hints.mainwin_vis_visible}, + {"mainwinvisx", & skin.hints.mainwin_vis_x}, + {"mainwinvisy", & skin.hints.mainwin_vis_y}, + {"mainwinvolumex", & skin.hints.mainwin_volume_x}, + {"mainwinvolumey", & skin.hints.mainwin_volume_y}, + {"mainwinwidth", & skin.hints.mainwin_width}, + {"textboxbitmapfontheight", & skin.hints.textbox_bitmap_font_height}, + {"textboxbitmapfontwidth", & skin.hints.textbox_bitmap_font_width}, +}; + +static int hint_pair_compare (const void * key, const void * pair) +{ + return g_ascii_strcasecmp ((const char *) key, ((const HintPair *) pair)->name); +} + +class HintsParser : public IniParser +{ +private: + bool valid_heading = false; + + void handle_heading (const char * heading) + { valid_heading = ! g_ascii_strcasecmp (heading, "skin"); } + + void handle_entry (const char * key, const char * value) + { + if (! valid_heading) + return; + + HintPair * pair = (HintPair *) bsearch (key, hint_pairs, + aud::n_elems (hint_pairs), sizeof (HintPair), hint_pair_compare); + + if (pair) + * pair->value_ptr = atoi (value); + } +}; + +void skin_load_hints (const char * path) +{ + VFSFile file = open_local_file_nocase (path, "skin.hints"); + if (file) + HintsParser ().parse (file); +} + +/* + * pledit.txt parsing + */ + +class PLColorsParser : public IniParser +{ +public: + PLColorsParser () : + valid_heading (false) {} + +private: + bool valid_heading; + + void handle_heading (const char * heading) + { valid_heading = ! g_ascii_strcasecmp (heading, "text"); } + + void handle_entry (const char * key, const char * value) + { + if (! valid_heading) + return; + + if (value[0] == '#') + value ++; + + uint32_t color = strtol (value, nullptr, 16); + + if (! g_ascii_strcasecmp (key, "normal")) + skin.colors[SKIN_PLEDIT_NORMAL] = color; + else if (! g_ascii_strcasecmp (key, "current")) + skin.colors[SKIN_PLEDIT_CURRENT] = color; + else if (! g_ascii_strcasecmp (key, "normalbg")) + skin.colors[SKIN_PLEDIT_NORMALBG] = color; + else if (! g_ascii_strcasecmp (key, "selectedbg")) + skin.colors[SKIN_PLEDIT_SELECTEDBG] = color; + } +}; + +void skin_load_pl_colors (const char * path) +{ + skin.colors[SKIN_PLEDIT_NORMAL] = 0x2499ff; + skin.colors[SKIN_PLEDIT_CURRENT] = 0xffeeff; + skin.colors[SKIN_PLEDIT_NORMALBG] = 0x0a120a; + skin.colors[SKIN_PLEDIT_SELECTEDBG] = 0x0a124a; + + VFSFile file = open_local_file_nocase (path, "pledit.txt"); + if (file) + PLColorsParser ().parse (file); +} + +/* + * region.txt parsing + */ + +class MaskParser : public IniParser +{ +public: + Index<int> numpoints[SKIN_MASK_COUNT]; + Index<int> pointlist[SKIN_MASK_COUNT]; + +private: + SkinMaskId current_id = SkinMaskId (-1); + + void handle_heading (const char * heading) + { + if (! g_ascii_strcasecmp (heading, "normal")) + current_id = SKIN_MASK_MAIN; + else if (! g_ascii_strcasecmp (heading, "windowshade")) + current_id = SKIN_MASK_MAIN_SHADE; + else if (! g_ascii_strcasecmp (heading, "equalizer")) + current_id = SKIN_MASK_EQ; + else if (! g_ascii_strcasecmp (heading, "equalizerws")) + current_id = SKIN_MASK_EQ_SHADE; + else + current_id = (SkinMaskId) -1; + } + + void handle_entry (const char * key, const char * value) + { + if (current_id == (SkinMaskId) -1) + return; + + if (! g_ascii_strcasecmp (key, "numpoints")) + numpoints[current_id] = string_to_int_array (value); + else if (! g_ascii_strcasecmp (key, "pointlist")) + pointlist[current_id] = string_to_int_array (value); + } +}; + +static Index<GdkRectangle> skin_create_mask (const Index<int> & num, + const Index<int> & point, int width, int height) +{ + Index<GdkRectangle> mask; + + int j = 0; + for (int i = 0; i < num.len (); i ++) + { + int n_points = num[i]; + if (n_points <= 0 || j + 2 * n_points > point.len ()) + break; + + int xmin = width, ymin = height, xmax = 0, ymax = 0; + + for (int k = 0; k < n_points; k ++) + { + int x = point[j + k * 2]; + int y = point[j + k * 2 + 1]; + + xmin = aud::min (xmin, x); + ymin = aud::min (ymin, y); + xmax = aud::max (xmax, x); + ymax = aud::max (ymax, y); + } + + if (xmax > xmin && ymax > ymin) + mask.append (xmin, ymin, xmax - xmin, ymax - ymin); + + j += n_points * 2; + } + + return mask; +} + +void skin_load_masks (const char * path) +{ + int sizes[SKIN_MASK_COUNT][2] = { + {skin.hints.mainwin_width, skin.hints.mainwin_height}, + {275, 16}, + {275, 116}, + {275, 16} + }; + + MaskParser parser; + VFSFile file = open_local_file_nocase (path, "region.txt"); + if (file) + parser.parse (file); + + for (int id = 0; id < SKIN_MASK_COUNT; id ++) + skin.masks[id] = skin_create_mask (parser.numpoints[id], + parser.pointlist[id], sizes[id][0], sizes[id][1]); +} diff --git a/src/skins/skin.cc b/src/skins/skin.cc new file mode 100644 index 0000000..ff3cab7 --- /dev/null +++ b/src/skins/skin.cc @@ -0,0 +1,457 @@ +/* Audacious + * Copyright (C) 2005-2015 Audacious development team. + * + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * + * Based on XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> + +#include <gtk/gtk.h> + +#include <libaudcore/audstrings.h> +#include <libaudcore/runtime.h> + +#include "plugin.h" +#include "skins_cfg.h" +#include "surface.h" +#include "skin.h" +#include "util.h" + +struct SkinPixmapIdMapping { + const char *name; + const char *alt_name; +}; + +static const SkinPixmapIdMapping skin_pixmap_id_map[] = { + {"main"}, + {"cbuttons"}, + {"titlebar"}, + {"shufrep"}, + {"text"}, + {"volume"}, + {"balance", "volume"}, + {"monoster"}, + {"playpaus"}, + {"nums_ex", "numbers"}, + {"posbar"}, + {"pledit"}, + {"eqmain"}, + {"eq_ex"} +}; + +static_assert (aud::n_elems (skin_pixmap_id_map) == SKIN_PIXMAP_COUNT, + "update skin_pixmap_id_map!"); + +static const uint32_t default_vis_colors[24] = { + COLOR (9, 34, 53), + COLOR (10, 18, 26), + COLOR (0, 54, 108), + COLOR (0, 58, 116), + COLOR (0, 62, 124), + COLOR (0, 66, 132), + COLOR (0, 70, 140), + COLOR (0, 74, 148), + COLOR (0, 78, 156), + COLOR (0, 82, 164), + COLOR (0, 86, 172), + COLOR (0, 92, 184), + COLOR (0, 98, 196), + COLOR (0, 104, 208), + COLOR (0, 110, 220), + COLOR (0, 116, 232), + COLOR (0, 122, 244), + COLOR (0, 128, 255), + COLOR (0, 128, 255), + COLOR (0, 104, 208), + COLOR (0, 80, 160), + COLOR (0, 56, 112), + COLOR (0, 32, 64), + COLOR (200, 200, 200) +}; + +Skin skin; + +static bool skin_load_pixmap_id (SkinPixmapId id, const char * path) +{ + StringBuf filename = skin_pixmap_locate (path, skin_pixmap_id_map[id].name, + skin_pixmap_id_map[id].alt_name); + + if (! filename) + { + AUDERR ("Skin does not contain a \"%s\" pixmap.\n", skin_pixmap_id_map[id].name); + return false; + } + + skin.pixmaps[id].capture (surface_new_from_file (filename)); + return skin.pixmaps[id] ? true : false; +} + +static int color_diff (uint32_t a, uint32_t b) +{ + return abs (COLOR_R (a) - COLOR_R (b)) + abs (COLOR_G (a) - COLOR_G (b)) + + abs (COLOR_B (a) - COLOR_B (b)); +} + +static void skin_get_textcolors (cairo_surface_t * s) +{ + /* + * Try to extract reasonable background and foreground colors + * from the font pixmap + */ + + /* Get a pixel from the middle of the space character */ + skin.colors[SKIN_TEXTBG] = surface_get_pixel (s, 152, 3); + + int max_d = -1; + for (int y = 0; y < 6; y ++) + { + for (int x = 1; x < 150; x ++) + { + uint32_t c = surface_get_pixel (s, x, y); + int d = color_diff (skin.colors[SKIN_TEXTBG], c); + if (d > max_d) + { + skin.colors[SKIN_TEXTFG] = c; + max_d = d; + } + } + } +} + +static void skin_get_eq_spline_colors (cairo_surface_t * s) +{ + if (cairo_image_surface_get_height (s) < 313) + return; + + for (int i = 0; i < 19; i ++) + skin.eq_spline_colors[i] = surface_get_pixel (s, 115, i + 294); +} + +static void skin_load_viscolor (const char * path) +{ + memcpy (skin.vis_colors, default_vis_colors, sizeof skin.vis_colors); + + VFSFile file = open_local_file_nocase (path, "viscolor.txt"); + if (! file) + return; + + Index<char> buffer = file.read_all (); + buffer.append (0); /* null-terminated */ + + char * string = buffer.begin (); + + for (int line = 0; string && line < 24; line ++) + { + char * next = text_parse_line (string); + Index<int> array = string_to_int_array (string); + + if (array.len () >= 3) + skin.vis_colors[line] = COLOR (array[0], array[1], array[2]); + + string = next; + } +} + +static void skin_numbers_generate_dash (CairoSurfacePtr & s) +{ + int w = cairo_image_surface_get_width (s.get ()); + if (w < 99 || w >= 108) + return; + + int h = cairo_image_surface_get_height (s.get ()); + cairo_surface_t * surface = surface_new (108, h); + + surface_copy_rect (s.get (), 0, 0, 99, h, surface, 0, 0); + surface_copy_rect (s.get (), 90, 0, 9, h, surface, 99, 0); + surface_copy_rect (s.get (), 20, 6, 5, 1, surface, 101, 6); + + s.capture (surface); +} + +static bool skin_load_pixmaps (const char * path) +{ + AUDDBG ("Loading pixmaps in %s\n", path); + + /* eq_ex.bmp was added after Winamp 2.0 so some skins do not include it */ + for (int i = 0; i < SKIN_PIXMAP_COUNT; i ++) + if (! skin_load_pixmap_id ((SkinPixmapId) i, path) && i != SKIN_EQ_EX) + return false; + + skin_get_textcolors (skin.pixmaps[SKIN_TEXT].get ()); + skin_get_eq_spline_colors (skin.pixmaps[SKIN_EQMAIN].get ()); + skin_numbers_generate_dash (skin.pixmaps[SKIN_NUMBERS]); + + return true; +} + +static bool skin_load_data (const char * path) +{ + AUDDBG ("Attempt to load skin \"%s\"\n", path); + + if (! g_file_test (path, G_FILE_TEST_EXISTS)) + return false; + + StringBuf archive_path; + if (file_is_archive (path)) + { + AUDDBG ("Attempt to load archive\n"); + archive_path.steal (archive_decompress (path)); + + if (! archive_path) + { + AUDDBG ("Unable to extract skin archive (%s)\n", path); + return false; + } + + path = archive_path; + } + + bool success = skin_load_pixmaps (path); + + if (success) + { + skin_load_hints (path); + skin_load_pl_colors (path); + skin_load_viscolor (path); + skin_load_masks (path); + } + else + AUDDBG ("Skin loading failed\n"); + + if (archive_path) + del_directory (archive_path); + + return success; +} + +bool skin_load (const char * path) +{ + /* save current skin data */ + Skin old_skin (std::move (skin)); + + /* reset to defaults */ + skin = Skin (); + + if (skin_load_data (path)) + { + aud_set_str ("skins", "skin", path); + return true; + } + + AUDWARN ("Unable to load skin (%s).\n", (const char *) path); + + /* restore old skin data */ + skin = std::move (old_skin); + return false; +} + +void skin_install_skin (const char * path) +{ + GError * err = nullptr; + char * data; + size_t len; + + if (! g_file_get_contents (path, & data, & len, & err)) + { + AUDERR ("Failed to read %s: %s\n", path, err->message); + g_error_free (err); + return; + } + + const char * user_skin_dir = skins_get_user_skin_dir (); + make_directory (user_skin_dir); + + StringBuf base = filename_get_base (path); + StringBuf target = filename_build ({user_skin_dir, base}); + + if (g_file_set_contents (target, data, len, & err)) + aud_set_str ("skins", "skin", target); + else + { + AUDERR ("Failed to write %s: %s\n", path, err->message); + g_error_free (err); + } + + g_free (data); +} + +void skin_draw_pixbuf (cairo_t * cr, SkinPixmapId id, int xsrc, int ysrc, int + xdest, int ydest, int width, int height) +{ + if (! skin.pixmaps[id]) + return; + + cairo_set_source_surface (cr, skin.pixmaps[id].get (), xdest - xsrc, ydest - ysrc); + cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST); + cairo_rectangle (cr, xdest, ydest, width, height); + cairo_fill (cr); +} + +static void skin_draw_playlistwin_frame_top (cairo_t * cr, int width, bool focus) +{ + /* The title bar skin consists of 2 sets of 4 images, 1 set + * for focused state and the other for unfocused. + * The 4 images are: + * + * a. right corner (25,20) + * b. left corner (25,20) + * c. tiler (25,20) + * d. title (100,20) + * + * min allowed width = 100+25+25 = 150 + */ + + /* get y offset of the pixmap set to use */ + int y = focus ? 0 : 21; + + /* left corner */ + skin_draw_pixbuf (cr, SKIN_PLEDIT, 0, y, 0, 0, 25, 20); + + /* titlebar title */ + skin_draw_pixbuf (cr, SKIN_PLEDIT, 26, y, (width - 100) / 2, 0, 100, 20); + + /* titlebar right corner */ + skin_draw_pixbuf (cr, SKIN_PLEDIT, 153, y, width - 25, 0, 25, 20); + + /* tile draw the remaining frame */ + + /* compute tile count */ + int c = (width - (100 + 25 + 25)) / 25; + + for (int i = 0; i < c / 2; i ++) + { + /* left of title */ + skin_draw_pixbuf (cr, SKIN_PLEDIT, 127, y, 25 + i * 25, 0, 25, 20); + + /* right of title */ + skin_draw_pixbuf (cr, SKIN_PLEDIT, 127, y, (width + 100) / 2 + i * 25, 0, 25, 20); + } + + if (c & 1) + { + /* Odd tile count, so one remaining to draw. Here we split + * it into two and draw half on either side of the title */ + skin_draw_pixbuf (cr, SKIN_PLEDIT, 127, y, ((c / 2) * 25) + 25, 0, 12, 20); + skin_draw_pixbuf (cr, SKIN_PLEDIT, 127, y, (width / 2) + ((c / 2) * 25) + 50, 0, 13, 20); + } +} + +static void skin_draw_playlistwin_frame_bottom (cairo_t * cr, int width, int height) +{ + /* The bottom frame skin consists of 1 set of 4 images. + * The 4 images are: + * + * a. left corner with menu buttons (125,38) + * b. visualization window (75,38) + * c. right corner with play buttons (150,38) + * d. frame tile (25,38) + * + * (min allowed width = 125+150+25=300 + */ + + /* bottom left corner (menu buttons) */ + skin_draw_pixbuf (cr, SKIN_PLEDIT, 0, 72, 0, height - 38, 125, 38); + + int c = (width - 275) / 25; + + /* draw visualization window, if width allows */ + if (c >= 3) + { + c -= 3; + skin_draw_pixbuf (cr, SKIN_PLEDIT, 205, 0, width - (150 + 75), height - 38, 75, 38); + } + + /* Bottom right corner (playbuttons etc) */ + skin_draw_pixbuf (cr, SKIN_PLEDIT, 126, 72, width - 150, height - 38, 150, 38); + + /* Tile draw the remaining undrawn portions */ + for (int i = 0; i < c; i ++) + skin_draw_pixbuf (cr, SKIN_PLEDIT, 179, 0, 125 + i * 25, height - 38, 25, 38); +} + +static void skin_draw_playlistwin_frame_sides (cairo_t * cr, int width, int height) +{ + /* The side frames consist of 2 tile images. 1 for the left, 1 for + * the right. + * a. left (12,29) + * b. right (19,29) + */ + + /* frame sides */ + for (int i = 0; i < (height - (20 + 38)) / 29; i ++) + { + /* left */ + skin_draw_pixbuf (cr, SKIN_PLEDIT, 0, 42, 0, 20 + i * 29, 12, 29); + + /* right */ + skin_draw_pixbuf (cr, SKIN_PLEDIT, 32, 42, width - 19, 20 + i * 29, 19, 29); + } +} + +void skin_draw_playlistwin_frame (cairo_t * cr, int width, int height, bool focus) +{ + skin_draw_playlistwin_frame_top (cr, width, focus); + skin_draw_playlistwin_frame_bottom (cr, width, height); + skin_draw_playlistwin_frame_sides (cr, width, height); +} + +void skin_draw_playlistwin_shaded (cairo_t * cr, int width, bool focus) +{ + /* The shade mode titlebar skin consists of 4 images: + * a) left corner offset (72,42) size (25,14) + * b) right corner, focused offset (99,57) size (50,14) + * c) right corner, unfocused offset (99,42) size (50,14) + * d) bar tile offset (72,57) size (25,14) + */ + + /* left corner */ + skin_draw_pixbuf (cr, SKIN_PLEDIT, 72, 42, 0, 0, 25, 14); + + /* bar tile */ + for (int i = 0; i < (width - 75) / 25; i ++) + skin_draw_pixbuf (cr, SKIN_PLEDIT, 72, 57, (i * 25) + 25, 0, 25, 14); + + /* right corner */ + skin_draw_pixbuf (cr, SKIN_PLEDIT, 99, focus ? 42 : 57, width - 50, 0, 50, 14); +} + +void skin_draw_mainwin_titlebar (cairo_t * cr, bool shaded, bool focus) +{ + /* The titlebar skin consists of 2 sets of 2 images, one for for + * shaded and the other for unshaded mode, giving a total of 4. + * The images are exactly 275x14 pixels, aligned and arranged + * vertically on each other in the pixmap in the following order: + * + * a) unshaded, focused offset (27, 0) + * b) unshaded, unfocused offset (27, 15) + * c) shaded, focused offset (27, 29) + * d) shaded, unfocused offset (27, 42) + */ + + int y_offset = shaded ? (focus ? 29 : 42) : (focus ? 0 : 15); + + skin_draw_pixbuf (cr, SKIN_TITLEBAR, 27, y_offset, 0, 0, + skin.hints.mainwin_width, 14); +} diff --git a/src/skins/ui_skin.h b/src/skins/skin.h index acc64c8..617ecb7 100644 --- a/src/skins/ui_skin.h +++ b/src/skins/skin.h @@ -29,6 +29,12 @@ #include <stdint.h> #include <gtk/gtk.h> +#include <libaudcore/index.h> +#include <libaudcore/objects.h> + +typedef SmartPtr<cairo_surface_t, cairo_surface_destroy> CairoSurfacePtr; +typedef SmartPtr<PangoFontDescription, pango_font_description_free> PangoFontDescPtr; + #define COLOR(r,g,b) (((uint32_t) (r) << 16) | ((uint32_t) (g) << 8) | (uint32_t) (b)) #define COLOR_R(c) ((int) (((c) & 0xff0000) >> 16)) #define COLOR_G(c) ((int) (((c) & 0xff00) >> 8)) @@ -70,7 +76,7 @@ typedef enum { SKIN_COLOR_COUNT } SkinColorId; -struct SkinProperties { +struct SkinHints { /* Vis properties */ int mainwin_vis_x = 24; int mainwin_vis_y = 43; @@ -167,38 +173,33 @@ struct SkinProperties { int textbox_bitmap_font_height = 6; }; -extern const SkinProperties skin_default_hints; +struct Skin { + SkinHints hints; + uint32_t colors[SKIN_COLOR_COUNT] {}; + uint32_t eq_spline_colors[19] {}; + uint32_t vis_colors[24] {}; -typedef struct { - char *path; - cairo_surface_t * pixmaps[SKIN_PIXMAP_COUNT]; - uint32_t colors[SKIN_COLOR_COUNT]; - uint32_t vis_colors[24]; - SkinProperties properties; -} Skin; - -extern Skin * active_skin; + CairoSurfacePtr pixmaps[SKIN_PIXMAP_COUNT]; + Index<GdkRectangle> masks[SKIN_MASK_COUNT]; +}; -gboolean init_skins(const char * path); -void cleanup_skins(void); +extern Skin skin; -gboolean active_skin_load(const char * path); +bool skin_load (const char * path); void skin_draw_pixbuf (cairo_t * cr, SkinPixmapId id, int xsrc, int ysrc, int xdest, int ydest, int width, int height); -void skin_get_eq_spline_colors(Skin * skin, uint32_t colors[19]); -void skin_install_skin(const char * path); +void skin_install_skin (const char * path); -void skin_draw_playlistwin_shaded (cairo_t * cr, int width, gboolean focus); -void skin_draw_playlistwin_frame (cairo_t * cr, int width, int height, - gboolean focus); -void skin_draw_mainwin_titlebar (cairo_t * cr, gboolean shaded, gboolean focus); +void skin_draw_playlistwin_shaded (cairo_t * cr, int width, bool focus); +void skin_draw_playlistwin_frame (cairo_t * cr, int width, int height, bool focus); +void skin_draw_mainwin_titlebar (cairo_t * cr, bool shaded, bool focus); /* ui_skin_load_ini.c */ -void skin_load_hints (Skin * skin, const char * path); -void skin_load_pl_colors (Skin * skin, const char * path); -void skin_load_masks (Skin * skin, const char * path, GdkRegion * masks[SKIN_MASK_COUNT]); +void skin_load_hints (const char * path); +void skin_load_pl_colors (const char * path); +void skin_load_masks (const char * path); static inline void set_cairo_color (cairo_t * cr, uint32_t c) { diff --git a/src/skins/skins_cfg.cc b/src/skins/skins_cfg.cc index 2538000..9c4fb97 100644 --- a/src/skins/skins_cfg.cc +++ b/src/skins/skins_cfg.cc @@ -26,58 +26,62 @@ #include <libaudcore/runtime.h> #include <libaudcore/preferences.h> #include <libaudcore/audstrings.h> +#include <libaudgui/libaudgui-gtk.h> #include "dnd.h" #include "skins_cfg.h" -#include "ui_equalizer.h" -#include "ui_main.h" -#include "ui_main_evlisteners.h" -#include "ui_playlist.h" -#include "ui_skin.h" -#include "ui_skinned_playlist.h" -#include "ui_skinned_textbox.h" -#include "ui_skinselector.h" -#include "ui_vis.h" +#include "main.h" +#include "vis-callbacks.h" +#include "playlist.h" +#include "skin.h" +#include "playlist-widget.h" +#include "textbox.h" +#include "skinselector.h" +#include "vis.h" #include "util.h" +#include "view.h" static const char * const skins_defaults[] = { - /* general */ - "autoscroll_songname", "TRUE", - "mainwin_font", "Sans Bold 9", - "mainwin_use_bitmapfont", "TRUE", - "playlist_font", "Sans Bold 8", - "show_remaining_time", "FALSE", - "twoway_scroll", "FALSE", - - /* visualizer */ - "analyzer_falloff", "3", /* FALLOFF_FAST */ - "analyzer_mode", "0", /* ANALYZER_NORMAL */ - "analyzer_peaks", "TRUE", - "analyzer_type", "1", /* ANALYZER_BARS */ - "peaks_falloff", "1", /* FALLOFF_SLOW */ - "scope_mode", "0", /* SCOPE_DOT */ - "vis_type", "0", /* VIS_ANALYZER */ - "voiceprint_mode", "0", /* VOICEPRINT_NORMAL */ - "vu_mode", "1", /* VU_SMOOTH */ - - /* windows */ - "always_on_top", "FALSE", - "double_size", "FALSE", - "equalizer_shaded", "FALSE", - "equalizer_visible", "FALSE", - "equalizer_x", "20", - "equalizer_y", "136", - "player_shaded", "FALSE", - "player_x", "20", - "player_y", "20", - "playlist_shaded", "FALSE", - "playlist_visible", "FALSE", - "playlist_x", "295", - "playlist_y", "20", - "playlist_width", "275", - "playlist_height", "232", - "sticky", "FALSE", - nullptr}; + /* general */ + "autoscroll_songname", "TRUE", + "mainwin_font", "Sans Bold 9", + "mainwin_use_bitmapfont", "TRUE", + "playlist_font", "Sans Bold 8", + "record", "FALSE", + "show_remaining_time", "FALSE", + "twoway_scroll", "FALSE", + + /* visualizer */ + "analyzer_falloff", aud::numeric_string<FALLOFF_FAST>::str, + "analyzer_mode", aud::numeric_string<ANALYZER_NORMAL>::str, + "analyzer_peaks", "TRUE", + "analyzer_type", aud::numeric_string<ANALYZER_BARS>::str, + "peaks_falloff", aud::numeric_string<FALLOFF_SLOW>::str, + "scope_mode", aud::numeric_string<SCOPE_DOT>::str, + "vis_type", aud::numeric_string<VIS_ANALYZER>::str, + "voiceprint_mode", aud::numeric_string<VOICEPRINT_NORMAL>::str, + "vu_mode", aud::numeric_string<VU_SMOOTH>::str, + + /* windows */ + "always_on_top", "FALSE", + "double_size", "FALSE", + "equalizer_shaded", "FALSE", + "equalizer_visible", "FALSE", + "equalizer_x", "20", + "equalizer_y", "136", + "player_shaded", "FALSE", + "player_x", "20", + "player_y", "20", + "playlist_shaded", "FALSE", + "playlist_visible", "FALSE", + "playlist_x", "295", + "playlist_y", "20", + "playlist_width", "275", + "playlist_height", "232", + "sticky", "FALSE", + + nullptr +}; skins_cfg_t config; @@ -123,7 +127,7 @@ static const struct { {"playlist_height", & config.playlist_height} }; -void skins_cfg_load (void) +void skins_cfg_load () { aud_config_set_defaults ("skins", skins_defaults); @@ -132,11 +136,9 @@ void skins_cfg_load (void) for (auto & nument : skins_numents) * nument.ptr = aud_get_int ("skins", nument.name); - - config.scale = aud_get_bool ("skins", "double_size") ? 2 : 1; } -void skins_cfg_save (void) +void skins_cfg_save () { for (auto & boolent : skins_boolents) aud_set_bool ("skins", boolent.name, * boolent.ptr); @@ -145,33 +147,36 @@ void skins_cfg_save (void) aud_set_int ("skins", nument.name, * nument.ptr); } -static void -mainwin_font_set_cb() +static void mainwin_font_set_cb () { - String font = aud_get_str ("skins", "mainwin_font"); - textbox_set_font (mainwin_info, config.mainwin_use_bitmapfont ? nullptr : (const char *) font); + if (! config.mainwin_use_bitmapfont) + mainwin_info->set_font (aud_get_str ("skins", "mainwin_font")); + else + mainwin_info->set_font (nullptr); } -static void -playlist_font_set_cb() +static void playlist_font_set_cb () { - String font = aud_get_str ("skins", "playlist_font"); - ui_skinned_playlist_set_font (playlistwin_list, font); + playlistwin_list->set_font (aud_get_str ("skins", "playlist_font")); } -static void autoscroll_set_cb (void) +static void autoscroll_set_cb () { - textbox_set_scroll (mainwin_info, config.autoscroll); - textbox_set_scroll (playlistwin_sinfo, config.autoscroll); + if (! aud_get_bool ("skins", "mainwin_shaded")) + mainwin_info->set_scroll (config.autoscroll); + if (aud_get_bool ("skins", "playlist_shaded")) + playlistwin_sinfo->set_scroll (config.autoscroll); } -static void vis_reset_cb (void) +static void vis_reset_cb () { - ui_vis_clear_data (mainwin_vis); - ui_svis_clear_data (mainwin_svis); - start_stop_visual (FALSE); + mainwin_vis->clear (); + mainwin_svis->clear (); + start_stop_visual (false); } +static void * create_skin_view (); + static const PreferencesWidget font_table_elements[] = { WidgetFonts (N_("Player:"), WidgetString ("skins", "mainwin_font", mainwin_font_set_cb), @@ -181,14 +186,11 @@ static const PreferencesWidget font_table_elements[] = { {N_("Select playlist font:")}) }; -static void * create_skin_view (void); - static const PreferencesWidget skins_widgets_general[] = { WidgetLabel (N_("<b>Skin</b>")), WidgetCustomGTK (create_skin_view), WidgetLabel (N_("<b>Fonts</b>")), - WidgetTable ({{font_table_elements}}, - WIDGET_CHILD), + WidgetTable ({{font_table_elements}}), WidgetCheck (N_("Use bitmap fonts (supports ASCII only)"), WidgetBool (config.mainwin_use_bitmapfont, mainwin_font_set_cb)), WidgetCheck (N_("Scroll song title"), @@ -240,14 +242,7 @@ static ComboItem vu_mode_elements[] = { ComboItem (N_("Smooth"), VU_SMOOTH) }; -static const PreferencesWidget skins_widgets_vis[] = { - WidgetLabel (N_("<b>Type</b>")), - WidgetCombo (N_("Visualization type:"), - WidgetInt (config.vis_type, vis_reset_cb), - {{vis_mode_elements}}), - WidgetLabel (N_("<b>Analyzer</b>")), - WidgetCheck (N_("Show peaks"), - WidgetBool (config.analyzer_peaks, vis_reset_cb)), +static const PreferencesWidget analyzer_table[] = { WidgetCombo (N_("Coloring:"), WidgetInt (config.analyzer_mode, vis_reset_cb), {{analyzer_mode_elements}}), @@ -259,8 +254,10 @@ static const PreferencesWidget skins_widgets_vis[] = { {{falloff_elements}}), WidgetCombo (N_("Peak falloff:"), WidgetInt (config.peaks_falloff, vis_reset_cb), - {{falloff_elements}}), - WidgetLabel (N_("<b>Miscellaneous</b>")), + {{falloff_elements}}) +}; + +static const PreferencesWidget misc_table[] = { WidgetCombo (N_("Scope Style:"), WidgetInt (config.scope_mode, vis_reset_cb), {{scope_mode_elements}}), @@ -272,6 +269,19 @@ static const PreferencesWidget skins_widgets_vis[] = { {{vu_mode_elements}}) }; +static const PreferencesWidget skins_widgets_vis[] = { + WidgetLabel (N_("<b>Type</b>")), + WidgetCombo (N_("Visualization type:"), + WidgetInt (config.vis_type, vis_reset_cb), + {{vis_mode_elements}}), + WidgetLabel (N_("<b>Analyzer</b>")), + WidgetCheck (N_("Show peaks"), + WidgetBool (config.analyzer_peaks, vis_reset_cb)), + WidgetTable ({{analyzer_table}}), + WidgetLabel (N_("<b>Miscellaneous</b>")), + WidgetTable ({{misc_table}}) +}; + static const NotebookTab skins_notebook_tabs[] = { {N_("General"), {skins_widgets_general}}, {N_("Visualization"), {skins_widgets_vis}} @@ -283,20 +293,17 @@ static const PreferencesWidget skins_widgets[] = { const PluginPreferences skins_prefs = {{skins_widgets}}; -void -on_skin_view_drag_data_received(GtkWidget * widget, - GdkDragContext * context, - int x, int y, - GtkSelectionData * selection_data, - unsigned info, unsigned time, - void * user_data) +void on_skin_view_drag_data_received (GtkWidget * widget, GdkDragContext * context, + int x, int y, GtkSelectionData * selection_data, unsigned info, unsigned time, void *) { const char * data = (const char *) gtk_selection_data_get_data (selection_data); g_return_if_fail (data); const char * end = strchr (data, '\r'); - if (! end) end = strchr (data, '\n'); - if (! end) end = data + strlen (data); + if (! end) + end = strchr (data, '\n'); + if (! end) + end = data + strlen (data); StringBuf path = str_copy (data, end - data); @@ -307,11 +314,12 @@ on_skin_view_drag_data_received(GtkWidget * widget, path.steal (std::move (path2)); } - if (file_is_archive(path)) + if (file_is_archive (path)) { - if (! active_skin_load (path)) + if (! skin_load (path)) return; + view_apply_skin (); skin_install_skin(path); if (skin_view) @@ -319,13 +327,13 @@ on_skin_view_drag_data_received(GtkWidget * widget, } } -static void * create_skin_view (void) +static void * create_skin_view () { GtkWidget * scrolled = gtk_scrolled_window_new (nullptr, nullptr); gtk_scrolled_window_set_policy ((GtkScrolledWindow *) scrolled, GTK_POLICY_NEVER, GTK_POLICY_ALWAYS); gtk_scrolled_window_set_shadow_type ((GtkScrolledWindow *) scrolled, GTK_SHADOW_IN); - gtk_widget_set_size_request (scrolled, -1, 160); + gtk_widget_set_size_request (scrolled, -1, audgui_get_dpi () * 3 / 2); skin_view = gtk_tree_view_new (); skin_view_realize ((GtkTreeView *) skin_view); diff --git a/src/skins/skins_cfg.h b/src/skins/skins_cfg.h index efa8fa7..d1df5de 100644 --- a/src/skins/skins_cfg.h +++ b/src/skins/skins_cfg.h @@ -45,15 +45,12 @@ typedef struct { extern skins_cfg_t config; -void skins_cfg_load(); -void skins_cfg_save(); - -void on_skin_view_drag_data_received(GtkWidget * widget, - GdkDragContext * context, - int x, int y, - GtkSelectionData * selection_data, - unsigned info, unsigned time, - void * user_data); +void skins_cfg_load (); +void skins_cfg_save (); + +void on_skin_view_drag_data_received (GtkWidget * widget, + GdkDragContext * context, int x, int y, GtkSelectionData * selection_data, + unsigned info, unsigned time, void * data); extern const PluginPreferences skins_prefs; diff --git a/src/skins/skinselector.cc b/src/skins/skinselector.cc new file mode 100644 index 0000000..fe8044c --- /dev/null +++ b/src/skins/skinselector.cc @@ -0,0 +1,237 @@ +/* + * ui_skinselector.c + * Copyright 1998-2003 XMMS Development Team + * Copyright 2003-2004 BMP Development Team + * Copyright 2011 John Lindgren + * + * This file is part of Audacious. + * + * Audacious 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, version 2 or version 3 of the License. + * + * Audacious 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 + * Audacious. If not, see <http://www.gnu.org/licenses/>. + * + * The Audacious team does not consider modular code linking to Audacious or + * using our public API to be a derived work. + */ + +#include <stdlib.h> +#include <string.h> + +#include <libaudcore/audstrings.h> +#include <libaudcore/i18n.h> +#include <libaudcore/runtime.h> +#include <libaudgui/libaudgui-gtk.h> + +#include "plugin.h" +#include "skin.h" +#include "skinselector.h" +#include "util.h" +#include "view.h" + +enum SkinViewCols { + SKIN_VIEW_COL_PREVIEW, + SKIN_VIEW_COL_FORMATTEDNAME, + SKIN_VIEW_COL_NAME, + SKIN_VIEW_N_COLS +}; + +struct SkinNode { + String name, desc, path; +}; + +static Index<SkinNode> skinlist; + +static void skin_view_on_cursor_changed (GtkTreeView * treeview); + +static GdkPixbuf * skin_get_preview (const char * path) +{ + GdkPixbuf * preview = nullptr; + + StringBuf archive_path; + if (file_is_archive (path)) + { + archive_path.steal (archive_decompress (path)); + if (! archive_path) + return nullptr; + + path = archive_path; + } + + StringBuf preview_path = skin_pixmap_locate (path, "main"); + if (preview_path) + preview = gdk_pixbuf_new_from_file (preview_path, nullptr); + + if (archive_path) + del_directory (archive_path); + + return preview; +} + +static GdkPixbuf * skin_get_thumbnail (const char * path) +{ + StringBuf base = filename_get_base (path); + base.insert (-1, ".png"); + + StringBuf thumbname = filename_build ({skins_get_skin_thumb_dir (), base}); + GdkPixbuf * thumb = nullptr; + + if (g_file_test (thumbname, G_FILE_TEST_EXISTS)) + thumb = gdk_pixbuf_new_from_file (thumbname, nullptr); + + if (! thumb) + { + thumb = skin_get_preview (path); + + if (thumb) + { + make_directory (skins_get_skin_thumb_dir ()); + gdk_pixbuf_save (thumb, thumbname, "png", nullptr, nullptr); + } + } + + if (thumb) + audgui_pixbuf_scale_within (& thumb, audgui_get_dpi () * 3 / 2); + + return thumb; +} + +static void scan_skindir_func (const char * path, const char * basename) +{ + if (g_file_test (path, G_FILE_TEST_IS_REGULAR)) + { + if (file_is_archive (path)) + skinlist.append (String (archive_basename (basename)), + String (_("Archived Winamp 2.x skin")), String (path)); + } + else if (g_file_test (path, G_FILE_TEST_IS_DIR)) + skinlist.append (String (basename), + String (_("Unarchived Winamp 2.x skin")), String (path)); +} + +static int skinlist_compare_func (const SkinNode & a, const SkinNode & b, void *) +{ + return str_compare (a.name, b.name); +} + +static void skinlist_update () +{ + skinlist.clear (); + + const char * user_skin_dir = skins_get_user_skin_dir (); + if (g_file_test (user_skin_dir, G_FILE_TEST_EXISTS)) + dir_foreach (user_skin_dir, scan_skindir_func); + + StringBuf path = filename_build ({aud_get_path (AudPath::DataDir), "Skins"}); + dir_foreach (path, scan_skindir_func); + + const char * skinsdir = getenv ("SKINSDIR"); + if (skinsdir) + { + for (const String & dir : str_list_to_index (skinsdir, ":")) + dir_foreach (dir, scan_skindir_func); + } + + skinlist.sort (skinlist_compare_func, nullptr); +} + +void skin_view_update (GtkTreeView * treeview) +{ + g_signal_handlers_block_by_func (treeview, (void *) skin_view_on_cursor_changed, nullptr); + + auto store = (GtkListStore *) gtk_tree_view_get_model (treeview); + gtk_list_store_clear (store); + + skinlist_update (); + + String current_path = aud_get_str ("skins", "skin"); + GtkTreePath * current_skin = nullptr; + + for (const SkinNode & node : skinlist) + { + GdkPixbuf * thumbnail = skin_get_thumbnail (node.path); + StringBuf formattedname = str_concat ({"<big><b>", node.name, + "</b></big>\n<i>", node.desc, "</i>"}); + + GtkTreeIter iter; + gtk_list_store_append (store, & iter); + gtk_list_store_set (store, & iter, + SKIN_VIEW_COL_PREVIEW, thumbnail, + SKIN_VIEW_COL_FORMATTEDNAME, (const char *) formattedname, + SKIN_VIEW_COL_NAME, (const char *) node.name, -1); + + if (thumbnail) + g_object_unref (thumbnail); + + if (! current_skin && strstr (current_path, node.name)) + current_skin = gtk_tree_model_get_path ((GtkTreeModel *) store, & iter); + } + + if (current_skin) + { + auto selection = gtk_tree_view_get_selection (treeview); + gtk_tree_selection_select_path (selection, current_skin); + gtk_tree_view_scroll_to_cell (treeview, current_skin, nullptr, true, 0.5, 0.5); + gtk_tree_path_free (current_skin); + } + + g_signal_handlers_unblock_by_func (treeview, (void *) skin_view_on_cursor_changed, nullptr); +} + +static void skin_view_on_cursor_changed (GtkTreeView * treeview) +{ + GtkTreeModel * model; + GtkTreeIter iter; + + auto selection = gtk_tree_view_get_selection (treeview); + if (! gtk_tree_selection_get_selected (selection, & model, & iter)) + return; + + GtkTreePath * path = gtk_tree_model_get_path (model, & iter); + int row = gtk_tree_path_get_indices (path)[0]; + g_return_if_fail (row >= 0 && row < skinlist.len ()); + gtk_tree_path_free (path); + + if (skin_load (skinlist[row].path)) + view_apply_skin (); +} + +void skin_view_realize (GtkTreeView * treeview) +{ + gtk_widget_show_all ((GtkWidget *) treeview); + + gtk_tree_view_set_rules_hint (treeview, true); + gtk_tree_view_set_headers_visible (treeview, false); + + GtkListStore * store = gtk_list_store_new (SKIN_VIEW_N_COLS, GDK_TYPE_PIXBUF, + G_TYPE_STRING, G_TYPE_STRING); + gtk_tree_view_set_model (treeview, (GtkTreeModel *) store); + g_object_unref (store); + + GtkTreeViewColumn * column = gtk_tree_view_column_new (); + gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); + gtk_tree_view_column_set_spacing (column, 16); + gtk_tree_view_append_column (treeview, column); + + GtkCellRenderer * renderer = gtk_cell_renderer_pixbuf_new (); + gtk_tree_view_column_pack_start (column, renderer, false); + gtk_tree_view_column_set_attributes (column, renderer, "pixbuf", + SKIN_VIEW_COL_PREVIEW, nullptr); + + renderer = gtk_cell_renderer_text_new (); + gtk_tree_view_column_pack_start (column, renderer, true); + gtk_tree_view_column_set_attributes (column, renderer, "markup", + SKIN_VIEW_COL_FORMATTEDNAME, nullptr); + + GtkTreeSelection * selection = gtk_tree_view_get_selection (treeview); + gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE); + + g_signal_connect (treeview, "cursor-changed", + (GCallback) skin_view_on_cursor_changed, nullptr); +} diff --git a/src/skins/ui_skinselector.h b/src/skins/skinselector.h index cb85e6b..cb85e6b 100644 --- a/src/skins/ui_skinselector.h +++ b/src/skins/skinselector.h diff --git a/src/skins/surface.cc b/src/skins/surface.cc index c71dd69..5847c61 100644 --- a/src/skins/surface.cc +++ b/src/skins/surface.cc @@ -34,10 +34,13 @@ cairo_surface_t * surface_new_from_file (const char * name) { GError * error = nullptr; GdkPixbuf * p = gdk_pixbuf_new_from_file (name, & error); - if (error) { + + if (error) + { AUDERR ("Error loading %s: %s.\n", name, error->message); g_error_free (error); } + if (! p) return nullptr; @@ -50,6 +53,7 @@ cairo_surface_t * surface_new_from_file (const char * name) cairo_destroy (cr); g_object_unref (p); + return surface; } diff --git a/src/skins/ui_svis.cc b/src/skins/svis.cc index a5af1ca..b8bde81 100644 --- a/src/skins/ui_svis.cc +++ b/src/skins/svis.cc @@ -27,28 +27,23 @@ #include <string.h> #include <libaudcore/objects.h> -#include "draw-compat.h" #include "skins_cfg.h" #include "surface.h" -#include "ui_skin.h" -#include "ui_vis.h" +#include "skin.h" +#include "vis.h" -static int svis_analyzer_colors[] = {14, 11, 8, 5, 2}; -static int svis_scope_colors[] = {20, 19, 18, 19, 20}; -static int svis_vu_normal_colors[] = {16, 14, 12, 10, 8, 6, 4, 2}; - -static struct { - gboolean active; - int data[75]; -} svis; +static const int svis_analyzer_colors[] = {14, 11, 8, 5, 2}; +static const int svis_scope_colors[] = {20, 19, 18, 19, 20}; +static const int svis_vu_normal_colors[] = {16, 14, 12, 10, 8, 6, 4, 2}; #define RGB_SEEK(x,y) (set = rgb + 38 * (y) + (x)) #define RGB_SET(c) (* set ++ = (c)) #define RGB_SET_Y(c) do {* set = (c); set += 38;} while (0) -#define RGB_SET_INDEX(c) RGB_SET (active_skin->vis_colors[c]) -#define RGB_SET_INDEX_Y(c) RGB_SET_Y (active_skin->vis_colors[c]) +#define RGB_SET_INDEX(c) RGB_SET (skin.vis_colors[c]) +#define RGB_SET_INDEX_Y(c) RGB_SET_Y (skin.vis_colors[c]) -DRAW_FUNC_BEGIN (ui_svis_draw) +void SmallVis::draw (cairo_t * cr) +{ uint32_t rgb[38 * 5]; uint32_t * set; @@ -60,14 +55,14 @@ DRAW_FUNC_BEGIN (ui_svis_draw) { case VIS_ANALYZER: { - gboolean bars = (config.analyzer_type == ANALYZER_BARS); + bool bars = (config.analyzer_type == ANALYZER_BARS); for (int x = 0; x < 38; x ++) { if (bars && (x % 3) == 2) continue; - int h = svis.data[bars ? (x / 3) : x]; + int h = m_data[bars ? (x / 3) : x]; h = aud::clamp (h, 0, 5); RGB_SEEK (x, 5 - h); @@ -86,7 +81,7 @@ DRAW_FUNC_BEGIN (ui_svis_draw) if (y == 2) continue; - int h = (svis.data[y / 3] * 8 + 19) / 38; + int h = (m_data[y / 3] * 8 + 19) / 38; h = aud::clamp (h, 0, 8); RGB_SEEK (0, y); @@ -105,7 +100,7 @@ DRAW_FUNC_BEGIN (ui_svis_draw) if (y == 2) continue; - int h = svis.data[y / 3]; + int h = m_data[y / 3]; h = aud::clamp (h, 0, 38); RGB_SEEK (0, y); @@ -120,7 +115,7 @@ DRAW_FUNC_BEGIN (ui_svis_draw) static const int scale[17] = {0, 0, 0, 0, 0, 0, 1, 1, 2, 3, 3, 4, 4, 4, 4, 4, 4}; - if (! svis.active) + if (! m_active) goto DRAW; switch (config.scope_mode) @@ -128,17 +123,17 @@ DRAW_FUNC_BEGIN (ui_svis_draw) case SCOPE_DOT: for (int x = 0; x < 38; x ++) { - int h = scale[aud::clamp (svis.data[2 * x], 0, 16)]; + int h = scale[aud::clamp (m_data[2 * x], 0, 16)]; RGB_SEEK (x, h); RGB_SET_INDEX (svis_scope_colors[h]); } break; case SCOPE_LINE: { - for (int x = 0; x < 37; x++) + for (int x = 0; x < 37; x ++) { - int h = scale[aud::clamp (svis.data[2 * x], 0, 16)]; - int h2 = scale[aud::clamp (svis.data[2 * (x + 1)], 0, 16)]; + int h = scale[aud::clamp (m_data[2 * x], 0, 16)]; + int h2 = scale[aud::clamp (m_data[2 * (x + 1)], 0, 16)]; if (h < h2) h2 --; else if (h > h2) {int temp = h; h = h2 + 1; h2 = temp;} @@ -148,19 +143,24 @@ DRAW_FUNC_BEGIN (ui_svis_draw) RGB_SET_INDEX_Y (svis_scope_colors[y]); } - int h = scale[aud::clamp (svis.data[74], 0, 16)]; + int h = scale[aud::clamp (m_data[74], 0, 16)]; RGB_SEEK (37, h); RGB_SET_INDEX (svis_scope_colors[h]); break; } default: /* SCOPE_SOLID */ - for (int x = 0; x < 38; x++) + for (int x = 0; x < 38; x ++) { - int h = scale[aud::clamp (svis.data[2 * x], 0, 16)]; + int h = scale[aud::clamp (m_data[2 * x], 0, 16)]; int h2; - if (h < 2) h2 = 2; - else {h2 = h; h = 2;} + if (h < 2) + h2 = 2; + else + { + h2 = h; + h = 2; + } RGB_SEEK (x, h); for (int y = h; y <= h2; y ++) @@ -172,44 +172,42 @@ DRAW_FUNC_BEGIN (ui_svis_draw) } } -DRAW:; +DRAW: cairo_surface_t * surf = cairo_image_surface_create_for_data ((unsigned char *) rgb, CAIRO_FORMAT_RGB24, 38, 5, 4 * 38); - cairo_scale (cr, config.scale, config.scale); cairo_set_source_surface (cr, surf, 0, 0); cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST); cairo_paint (cr); cairo_surface_destroy (surf); -DRAW_FUNC_END +} -GtkWidget * ui_svis_new (void) +SmallVis::SmallVis () { - GtkWidget * wid = gtk_drawing_area_new (); - gtk_widget_set_size_request (wid, 38 * config.scale, 5 * config.scale); - gtk_widget_add_events (wid, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); - DRAW_CONNECT (wid, ui_svis_draw); - return wid; + set_scale (config.scale); + add_drawable (38, 5); + clear (); } -void ui_svis_clear_data (GtkWidget * widget) +void SmallVis::clear () { - memset (& svis, 0, sizeof svis); - gtk_widget_queue_draw (widget); + m_active = false; + memset (m_data, 0, sizeof m_data); + queue_draw (); } -void ui_svis_timeout_func (GtkWidget * widget, unsigned char * data) +void SmallVis::render (const unsigned char * data) { if (config.vis_type == VIS_VOICEPRINT) { for (int i = 0; i < 2; i ++) - svis.data[i] = data[i]; + m_data[i] = data[i]; } else { for (int i = 0; i < 75; i ++) - svis.data[i] = data[i]; + m_data[i] = data[i]; } - svis.active = TRUE; - gtk_widget_queue_draw (widget); + m_active = true; + draw_now (); } diff --git a/src/skins/textbox.cc b/src/skins/textbox.cc new file mode 100644 index 0000000..18bf783 --- /dev/null +++ b/src/skins/textbox.cc @@ -0,0 +1,311 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2011 John Lindgren + * + * Based on: + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include <string.h> + +#include <libaudcore/audstrings.h> +#include <libaudcore/hook.h> +#include <libaudcore/objects.h> + +#include "skins_cfg.h" +#include "skin.h" +#include "textbox.h" + +#define DELAY 50 + +static Index<TextBox *> textboxes; + +void TextBox::draw (cairo_t * cr) +{ + if (m_scrolling) + { + cairo_set_source_surface (cr, m_buf.get (), -m_offset * config.scale, 0); + cairo_paint (cr); + + if (-m_offset + m_buf_width < m_width) + { + cairo_set_source_surface (cr, m_buf.get (), + (-m_offset + m_buf_width) * config.scale, 0); + cairo_paint (cr); + } + } + else + { + cairo_set_source_surface (cr, m_buf.get (), 0, 0); + cairo_paint (cr); + } +} + +bool TextBox::button_press (GdkEventButton * event) +{ + return press ? press (event) : false; +} + +void TextBox::scroll_timeout () +{ + if (m_delay < DELAY) + { + m_delay ++; + return; + } + + if (m_two_way && m_backward) + m_offset --; + else + m_offset ++; + + if (m_two_way && (m_backward ? (m_offset <= 0) : (m_offset + m_width >= m_buf_width))) + { + m_backward = ! m_backward; + m_delay = 0; + } + + if (! m_two_way && m_offset >= m_buf_width) + m_offset = 0; + + draw_now (); +} + +void TextBox::render_vector (const char * text) +{ + PangoLayout * layout = gtk_widget_create_pango_layout (gtk_dr (), text); + pango_layout_set_font_description (layout, m_font.get ()); + + PangoRectangle ink, logical; + pango_layout_get_pixel_extents (layout, & ink, & logical); + + /* use logical width so as not to trim off the trailing space of the " --- " */ + /* use ink height since vertical space is quite limited */ + int width = aud::max (-ink.x + logical.width, 1); + int height = aud::max (ink.height, 1); + + resize (m_width * config.scale, height); + + m_buf_width = aud::max ((width + config.scale - 1) / config.scale, m_width); + m_buf.capture (cairo_image_surface_create (CAIRO_FORMAT_ARGB32, + m_buf_width * config.scale, height)); + + cairo_t * cr = cairo_create (m_buf.get ()); + + set_cairo_color (cr, skin.colors[SKIN_TEXTBG]); + cairo_paint (cr); + + cairo_move_to (cr, -ink.x, -ink.y); + set_cairo_color (cr, skin.colors[SKIN_TEXTFG]); + pango_cairo_show_layout (cr, layout); + + cairo_destroy (cr); + g_object_unref (layout); +} + +static void lookup_char (const char c, int * x, int * y) +{ + int tx, ty; + + switch (c) + { + case '"': tx = 26; ty = 0; break; + case '@': tx = 27; ty = 0; break; + case ' ': tx = 29; ty = 0; break; + case ':': + case ';': + case '|': tx = 12; ty = 1; break; + case '(': + case '{': tx = 13; ty = 1; break; + case ')': + case '}': tx = 14; ty = 1; break; + case '-': + case '~': tx = 15; ty = 1; break; + case '`': + case '\'': tx = 16; ty = 1; break; + case '!': tx = 17; ty = 1; break; + case '_': tx = 18; ty = 1; break; + case '+': tx = 19; ty = 1; break; + case '\\': tx = 20; ty = 1; break; + case '/': tx = 21; ty = 1; break; + case '[': tx = 22; ty = 1; break; + case ']': tx = 23; ty = 1; break; + case '^': tx = 24; ty = 1; break; + case '&': tx = 25; ty = 1; break; + case '%': tx = 26; ty = 1; break; + case '.': + case ',': tx = 27; ty = 1; break; + case '=': tx = 28; ty = 1; break; + case '$': tx = 29; ty = 1; break; + case '#': tx = 30; ty = 1; break; + case '?': tx = 3; ty = 2; break; + case '*': tx = 4; ty = 2; break; + default: tx = 3; ty = 2; break; /* '?' */ + } + + * x = tx * skin.hints.textbox_bitmap_font_width; + * y = ty * skin.hints.textbox_bitmap_font_height; +} + +void TextBox::render_bitmap (const char * text) +{ + int cw = skin.hints.textbox_bitmap_font_width; + int ch = skin.hints.textbox_bitmap_font_height; + + resize (m_width * config.scale, ch * config.scale); + + long len; + gunichar * utf32 = g_utf8_to_ucs4 (text, -1, nullptr, & len, nullptr); + g_return_if_fail (utf32); + + m_buf_width = aud::max (cw * (int) len, m_width); + m_buf.capture (cairo_image_surface_create (CAIRO_FORMAT_ARGB32, + m_buf_width * config.scale, ch * config.scale)); + + cairo_t * cr = cairo_create (m_buf.get ()); + if (config.scale != 1) + cairo_scale (cr, config.scale, config.scale); + + gunichar * s = utf32; + for (int x = 0; x < m_buf_width; x += cw) + { + gunichar c = * s ? * s ++ : ' '; + int cx = 0, cy = 0; + + if (c >= 'A' && c <= 'Z') + cx = cw * (c - 'A'); + else if (c >= 'a' && c <= 'z') + cx = cw * (c - 'a'); + else if (c >= '0' && c <= '9') + { + cx = cw * (c - '0'); + cy = ch; + } + else + lookup_char (c, & cx, & cy); + + skin_draw_pixbuf (cr, SKIN_TEXT, cx, cy, x, 0, cw, ch); + } + + cairo_destroy (cr); + g_free (utf32); +} + +void TextBox::render () +{ + m_scrolling = false; + m_backward = false; + m_offset = 0; + m_delay = 0; + + const char * text = m_text ? m_text : ""; + + if (m_font) + render_vector (text); + else + render_bitmap (text); + + if (m_may_scroll && m_buf_width > m_width) + { + m_scrolling = true; + + if (! m_two_way) + { + StringBuf temp = str_printf ("%s --- ", text); + + if (m_font) + render_vector (temp); + else + render_bitmap (temp); + } + } + + queue_draw (); + + if (m_scrolling) + scroll_timer.start (); + else + scroll_timer.stop (); +} + +void TextBox::set_width (int width) +{ + if (m_width != width) + { + m_width = width; + render (); + } +} + +void TextBox::set_text (const char * text) +{ + if (strcmp_safe (m_text, text)) + { + m_text = String (text); + render (); + } +} + +void TextBox::set_font (const char * font) +{ + if (font) + m_font.capture (pango_font_description_from_string (font)); + else + m_font.clear (); + + render (); +} + +void TextBox::set_scroll (bool scroll) +{ + if (m_may_scroll != scroll || m_two_way != config.twoway_scroll) + { + m_may_scroll = scroll; + m_two_way = config.twoway_scroll; + render (); + } +} + +TextBox::~TextBox () +{ + int idx = textboxes.find (this); + if (idx >= 0) + textboxes.remove (idx, 1); +} + +TextBox::TextBox (int width, const char * font, bool scroll) : + m_width (width), + m_may_scroll (scroll), + m_two_way (config.twoway_scroll) +{ + /* size is computed by set_font() */ + add_input (1, 1, false, true); + set_font (font); + + textboxes.append (this); +} + +void TextBox::update_all () +{ + for (TextBox * textbox : textboxes) + textbox->render (); +} diff --git a/src/skins/textbox.h b/src/skins/textbox.h new file mode 100644 index 0000000..f587e21 --- /dev/null +++ b/src/skins/textbox.h @@ -0,0 +1,80 @@ +/* + * Audacious - a cross-platform multimedia player + * Copyright (c) 2007 Tomasz Moń + * Copyright (c) 2011 John Lindgren + * + * Based on: + * BMP - Cross-platform multimedia player + * Copyright (C) 2003-2004 BMP development team. + * XMMS: + * Copyright (C) 1998-2003 XMMS development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#ifndef SKINS_UI_SKINNED_TEXTBOX_H +#define SKINS_UI_SKINNED_TEXTBOX_H + +#include <libaudcore/hook.h> +#include <libaudcore/objects.h> + +#include "widget.h" + +typedef SmartPtr<cairo_surface_t, cairo_surface_destroy> CairoSurfacePtr; +typedef SmartPtr<PangoFontDescription, pango_font_description_free> PangoFontDescPtr; + +class TextBox : public Widget +{ +public: + TextBox (int width, const char * font, bool scroll); + ~TextBox (); + + void set_width (int width); + const String & get_text () { return m_text; } + void set_text (const char * text); + void set_font (const char * font); + void set_scroll (bool scroll); + + typedef bool (* PressCB) (GdkEventButton *); + void on_press (PressCB callback) { press = callback; } + + static void update_all (); + +private: + virtual void draw (cairo_t * cr); + virtual bool button_press (GdkEventButton * event); + + void scroll_timeout (); + void render_vector (const char * text); + void render_bitmap (const char * text); + void render (); + + const Timer<TextBox> + scroll_timer {TimerRate::Hz30, this, & TextBox::scroll_timeout}; + + String m_text; + PangoFontDescPtr m_font; + CairoSurfacePtr m_buf; + + int m_width = 0, m_buf_width = 0; + bool m_may_scroll = false, m_two_way = false; + bool m_scrolling = false, m_backward = false; + int m_offset = 0, m_delay = 0; + + PressCB press = nullptr; +}; + +#endif diff --git a/src/skins/ui_equalizer.cc b/src/skins/ui_equalizer.cc deleted file mode 100644 index 9cb2edf..0000000 --- a/src/skins/ui_equalizer.cc +++ /dev/null @@ -1,498 +0,0 @@ -/* Audacious - Cross-platform multimedia player - * Copyright (C) 2005-2014 Audacious development team. - * - * Based on BMP: - * Copyright (C) 2003-2004 BMP development team. - * - * Based on XMMS: - * Copyright (C) 1998-2003 XMMS development team. - * - * 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; under version 3 of the License. - * - * 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 <http://www.gnu.org/licenses>. - * - * The Audacious team does not consider modular code linking to - * Audacious or using our public API to be a derived work. - */ - -#include <string.h> -#include <gtk/gtk.h> - -#include <libaudcore/audstrings.h> -#include <libaudcore/drct.h> -#include <libaudcore/hook.h> -#include <libaudcore/i18n.h> -#include <libaudcore/runtime.h> -#include <libaudgui/libaudgui-gtk.h> - -#include "menus.h" -#include "plugin.h" -#include "preset-list.h" -#include "skins_cfg.h" -#include "ui_equalizer.h" -#include "ui_main.h" -#include "ui_skinned_button.h" -#include "ui_skinned_equalizer_graph.h" -#include "ui_skinned_equalizer_slider.h" -#include "ui_skinned_horizontal_slider.h" -#include "ui_skinned_window.h" -#include "util.h" -#include "view.h" - -static float equalizerwin_get_preamp (void); -static float equalizerwin_get_band (int band); -static void equalizerwin_set_preamp (float preamp); -static void equalizerwin_set_band (int band, float value); - -static void playback_begin_cb (void *, void *); - -GtkWidget *equalizerwin; -GtkWidget *equalizerwin_graph; - -static GtkWidget *equalizerwin_on, *equalizerwin_auto; - -static GtkWidget *equalizerwin_close, *equalizerwin_shade; -static GtkWidget *equalizerwin_shaded_close, *equalizerwin_shaded_shade; -static GtkWidget *equalizerwin_presets; -static GtkWidget *equalizerwin_preamp,*equalizerwin_bands[10]; -static GtkWidget *equalizerwin_volume, *equalizerwin_balance; - -Index<EqualizerPreset> equalizer_presets, equalizer_auto_presets; - -static void -equalizerwin_shade_toggle(void) -{ - view_set_equalizer_shaded (! aud_get_bool ("skins", "equalizer_shaded")); -} - -void -equalizerwin_eq_changed(void) -{ - aud_set_double (nullptr, "equalizer_preamp", equalizerwin_get_preamp ()); - - double bands[AUD_EQ_NBANDS]; - for (int i = 0; i < AUD_EQ_NBANDS; i ++) - bands[i] = equalizerwin_get_band (i); - - aud_eq_set_bands (bands); -} - -void equalizerwin_apply_preset (const EqualizerPreset & preset) -{ - equalizerwin_set_preamp (preset.preamp); - for (int i = 0; i < AUD_EQ_NBANDS; i ++) - equalizerwin_set_band (i, preset.bands[i]); -} - -void equalizerwin_update_preset (EqualizerPreset & preset) -{ - preset.preamp = equalizerwin_get_preamp (); - for (int i = 0; i < AUD_EQ_NBANDS; i ++) - preset.bands[i] = equalizerwin_get_band (i); -} - -void equalizerwin_import_presets (Index<EqualizerPreset> && presets) -{ - equalizer_presets.move_from (presets, 0, -1, -1, true, true); - aud_eq_write_presets (equalizer_presets, "eq.preset"); -} - -static void eq_on_cb (GtkWidget * button, GdkEventButton * event) - {aud_set_bool (nullptr, "equalizer_active", button_get_active (button)); } -static void eq_auto_cb (GtkWidget * button, GdkEventButton * event) - {aud_set_bool (nullptr, "equalizer_autoload", button_get_active (equalizerwin_auto)); } - -static void update_from_config (void * unused1, void * unused2) -{ - button_set_active (equalizerwin_on, aud_get_bool (nullptr, "equalizer_active")); - eq_slider_set_val (equalizerwin_preamp, aud_get_double (nullptr, "equalizer_preamp")); - - double bands[AUD_EQ_NBANDS]; - aud_eq_get_bands (bands); - - for (int i = 0; i < AUD_EQ_NBANDS; i ++) - eq_slider_set_val (equalizerwin_bands[i], bands[i]); - - eq_graph_update (equalizerwin_graph); -} - -static void eq_presets_cb (GtkWidget * button, GdkEventButton * event) -{ - menu_popup (UI_MENU_EQUALIZER_PRESET, event->x_root, event->y_root, FALSE, - FALSE, event->button, event->time); -} - -static gboolean -equalizerwin_press(GtkWidget * widget, GdkEventButton * event, - void * callback_data) -{ - if (event->button == 1 && event->type == GDK_2BUTTON_PRESS && - event->window == gtk_widget_get_window (widget) && - event->y < 14 * config.scale) - { - equalizerwin_shade_toggle (); - return TRUE; - } - - if (event->button == 3) - { - menu_popup (UI_MENU_MAIN, event->x_root, event->y_root, FALSE, FALSE, - event->button, event->time); - return TRUE; - } - - return FALSE; -} - -static void -equalizerwin_close_cb(void) -{ - view_set_show_equalizer (FALSE); -} - -static void eqwin_volume_set_knob (void) -{ - int pos = hslider_get_pos (equalizerwin_volume); - - int x; - if (pos < 32) - x = 1; - else if (pos < 63) - x = 4; - else - x = 7; - - hslider_set_knob (equalizerwin_volume, x, 30, x, 30); -} - -void equalizerwin_set_volume_slider (int percent) -{ - hslider_set_pos (equalizerwin_volume, (percent * 94 + 50) / 100); - eqwin_volume_set_knob (); -} - -static void eqwin_volume_motion_cb (void) -{ - eqwin_volume_set_knob (); - int pos = hslider_get_pos (equalizerwin_volume); - int v = (pos * 100 + 47) / 94; - - mainwin_adjust_volume_motion(v); - mainwin_set_volume_slider(v); -} - -static void eqwin_volume_release_cb (void) -{ - eqwin_volume_set_knob (); - mainwin_adjust_volume_release(); -} - -static void eqwin_balance_set_knob (void) -{ - int pos = hslider_get_pos (equalizerwin_balance); - - int x; - if (pos < 13) - x = 11; - else if (pos < 26) - x = 14; - else - x = 17; - - hslider_set_knob (equalizerwin_balance, x, 30, x, 30); -} - -void equalizerwin_set_balance_slider (int percent) -{ - if (percent > 0) - hslider_set_pos (equalizerwin_balance, 19 + (percent * 19 + 50) / 100); - else - hslider_set_pos (equalizerwin_balance, 19 + (percent * 19 - 50) / 100); - - eqwin_balance_set_knob (); -} - -static void eqwin_balance_motion_cb (void) -{ - eqwin_balance_set_knob (); - int pos = hslider_get_pos (equalizerwin_balance); - pos = aud::min(pos, 38); /* The skin uses a even number of pixels - for the balance-slider *sigh* */ - int b; - if (pos > 19) - b = ((pos - 19) * 100 + 9) / 19; - else - b = ((pos - 19) * 100 - 9) / 19; - - mainwin_adjust_balance_motion(b); - mainwin_set_balance_slider(b); -} - -static void eqwin_balance_release_cb (void) -{ - eqwin_balance_set_knob (); - mainwin_adjust_balance_release(); -} - -static void -equalizerwin_create_widgets(void) -{ - equalizerwin_on = button_new_toggle (25, 12, 10, 119, 128, 119, 69, 119, 187, 119, SKIN_EQMAIN, SKIN_EQMAIN); - window_put_widget (equalizerwin, FALSE, equalizerwin_on, 14, 18); - button_set_active (equalizerwin_on, aud_get_bool (nullptr, "equalizer_active")); - button_on_release (equalizerwin_on, eq_on_cb); - - equalizerwin_auto = button_new_toggle (33, 12, 35, 119, 153, 119, 94, 119, 212, 119, SKIN_EQMAIN, SKIN_EQMAIN); - window_put_widget (equalizerwin, FALSE, equalizerwin_auto, 39, 18); - button_set_active (equalizerwin_auto, aud_get_bool (nullptr, "equalizer_autoload")); - button_on_release (equalizerwin_auto, eq_auto_cb); - - equalizerwin_presets = button_new (44, 12, 224, 164, 224, 176, SKIN_EQMAIN, SKIN_EQMAIN); - window_put_widget (equalizerwin, FALSE, equalizerwin_presets, 217, 18); - button_on_release (equalizerwin_presets, eq_presets_cb); - - equalizerwin_close = button_new (9, 9, 0, 116, 0, 125, SKIN_EQMAIN, SKIN_EQMAIN); - window_put_widget (equalizerwin, FALSE, equalizerwin_close, 264, 3); - button_on_release (equalizerwin_close, (ButtonCB) equalizerwin_close_cb); - - equalizerwin_shade = button_new (9, 9, 254, 137, 1, 38, SKIN_EQMAIN, SKIN_EQ_EX); - window_put_widget (equalizerwin, FALSE, equalizerwin_shade, 254, 3); - button_on_release (equalizerwin_shade, (ButtonCB) equalizerwin_shade_toggle); - - equalizerwin_shaded_close = button_new (9, 9, 11, 38, 11, 47, SKIN_EQ_EX, SKIN_EQ_EX); - window_put_widget (equalizerwin, TRUE, equalizerwin_shaded_close, 264, 3); - button_on_release (equalizerwin_shaded_close, (ButtonCB) equalizerwin_close_cb); - - equalizerwin_shaded_shade = button_new (9, 9, 254, 3, 1, 47, SKIN_EQ_EX, SKIN_EQ_EX); - window_put_widget (equalizerwin, TRUE, equalizerwin_shaded_shade, 254, 3); - button_on_release (equalizerwin_shaded_shade, (ButtonCB) equalizerwin_shade_toggle); - - equalizerwin_graph = eq_graph_new (); - gtk_widget_set_no_show_all (equalizerwin_graph, TRUE); // shown or hidden in skin_load() - window_put_widget (equalizerwin, FALSE, equalizerwin_graph, 86, 17); - - equalizerwin_preamp = eq_slider_new (_("Preamp")); - window_put_widget (equalizerwin, FALSE, equalizerwin_preamp, 21, 38); - eq_slider_set_val (equalizerwin_preamp, aud_get_double (nullptr, "equalizer_preamp")); - - const char * const bandnames[AUD_EQ_NBANDS] = {N_("31 Hz"), - N_("63 Hz"), N_("125 Hz"), N_("250 Hz"), N_("500 Hz"), N_("1 kHz"), - N_("2 kHz"), N_("4 kHz"), N_("8 kHz"), N_("16 kHz")}; - double bands[AUD_EQ_NBANDS]; - aud_eq_get_bands (bands); - - for (int i = 0; i < AUD_EQ_NBANDS; i ++) - { - equalizerwin_bands[i] = eq_slider_new (_(bandnames[i])); - window_put_widget (equalizerwin, FALSE, equalizerwin_bands[i], 78 + 18 * i, 38); - eq_slider_set_val (equalizerwin_bands[i], bands[i]); - } - - equalizerwin_volume = hslider_new (0, 94, SKIN_EQ_EX, 97, 8, 61, 4, 3, 7, 1, 30, 1, 30); - window_put_widget (equalizerwin, TRUE, equalizerwin_volume, 61, 4); - hslider_on_motion (equalizerwin_volume, eqwin_volume_motion_cb); - hslider_on_release (equalizerwin_volume, eqwin_volume_release_cb); - - equalizerwin_balance = hslider_new (0, 39, SKIN_EQ_EX, 42, 8, 164, 4, 3, 7, 11, 30, 11, 30); - window_put_widget (equalizerwin, TRUE, equalizerwin_balance, 164, 4); - hslider_on_motion (equalizerwin_balance, eqwin_balance_motion_cb); - hslider_on_release (equalizerwin_balance, eqwin_balance_release_cb); -} - -static void eq_win_draw (GtkWidget * window, cairo_t * cr) -{ - gboolean shaded = aud_get_bool ("skins", "equalizer_shaded"); - - skin_draw_pixbuf (cr, SKIN_EQMAIN, 0, 0, 0, 0, 275, shaded ? 14 : 116); - - if (shaded) - skin_draw_pixbuf (cr, SKIN_EQ_EX, 0, 0, 0, 0, 275, 14); - else - skin_draw_pixbuf (cr, SKIN_EQMAIN, 0, 134, 0, 0, 275, 14); -} - -static void -equalizerwin_create_window(void) -{ - gboolean shaded = aud_get_bool ("skins", "equalizer_shaded"); - - equalizerwin = window_new (& config.equalizer_x, & config.equalizer_y, 275, - shaded ? 14 : 116, FALSE, shaded, eq_win_draw); - - gtk_window_set_title(GTK_WINDOW(equalizerwin), _("Audacious Equalizer")); - - /* this will hide only mainwin. it's annoying! yaz */ - gtk_window_set_transient_for(GTK_WINDOW(equalizerwin), - GTK_WINDOW(mainwin)); - gtk_window_set_skip_pager_hint(GTK_WINDOW(equalizerwin), TRUE); - gtk_window_set_skip_taskbar_hint(GTK_WINDOW(equalizerwin), TRUE); - - gtk_widget_set_app_paintable(equalizerwin, TRUE); - - g_signal_connect (equalizerwin, "delete-event", (GCallback) handle_window_close, nullptr); - g_signal_connect (equalizerwin, "button-press-event", (GCallback) equalizerwin_press, nullptr); - g_signal_connect (equalizerwin, "key-press-event", (GCallback) mainwin_keypress, nullptr); -} - -static void equalizerwin_destroyed (void) -{ - hook_dissociate ("set equalizer_active", (HookFunction) update_from_config); - hook_dissociate ("set equalizer_bands", (HookFunction) update_from_config); - hook_dissociate ("set equalizer_preamp", (HookFunction) update_from_config); - - hook_dissociate ("playback begin", playback_begin_cb); - - equalizer_presets.clear (); - equalizer_auto_presets.clear (); -} - -void -equalizerwin_create(void) -{ - equalizer_presets = aud_eq_read_presets("eq.preset"); - equalizer_auto_presets = aud_eq_read_presets("eq.auto_preset"); - - equalizerwin_create_window(); - - gtk_window_add_accel_group ((GtkWindow *) equalizerwin, menu_get_accel_group ()); - - equalizerwin_create_widgets(); - window_show_all (equalizerwin); - - g_signal_connect (equalizerwin, "destroy", (GCallback) equalizerwin_destroyed, nullptr); - - hook_associate ("set equalizer_active", (HookFunction) update_from_config, nullptr); - hook_associate ("set equalizer_bands", (HookFunction) update_from_config, nullptr); - hook_associate ("set equalizer_preamp", (HookFunction) update_from_config, nullptr); - - /* Load preset for the first song. FIXME: Doing this at interface load is - really too late as the song may already be started. Really, this stuff - shouldn't be in the interface plugin at all but in core. -jlindgren */ - if (aud_drct_get_playing ()) - playback_begin_cb (nullptr, nullptr); - - hook_associate ("playback begin", playback_begin_cb, nullptr); -} - -static int equalizerwin_find_preset (Index<EqualizerPreset> & list, const char * name) -{ - for (int p = 0; p < list.len (); p ++) - { - if (! g_ascii_strcasecmp (list[p].name, name)) - return p; - } - - return -1; -} - -gboolean equalizerwin_load_preset (Index<EqualizerPreset> & list, const char * name) -{ - int p = equalizerwin_find_preset (list, name); - if (p < 0) - return FALSE; - - equalizerwin_apply_preset (list[p]); - return TRUE; -} - -void equalizerwin_save_preset (Index<EqualizerPreset> & list, const char * name, const char * filename) -{ - int p = equalizerwin_find_preset (list, name); - - if (p < 0) - { - list.append (String (name)); - p = list.len () - 1; - } - - equalizerwin_update_preset (list[p]); - - aud_eq_write_presets (list, filename); -} - -void equalizerwin_delete_preset (Index<EqualizerPreset> & list, const char * name, const char * filename) -{ - int p = equalizerwin_find_preset (list, name); - if (p < 0) - return; - - list.remove (p, 1); - aud_eq_write_presets (list, filename); -} - -static gboolean equalizerwin_read_aud_preset (const char * filename) -{ - EqualizerPreset preset; - - VFSFile file (filename, "r"); - if (! file || ! aud_load_preset_file (preset, file)) - return FALSE; - - equalizerwin_apply_preset (preset); - return TRUE; -} - -static void equalizerwin_set_preamp (float preamp) -{ - eq_slider_set_val (equalizerwin_preamp, preamp); - equalizerwin_eq_changed(); -} - -static void equalizerwin_set_band (int band, float value) -{ - g_return_if_fail(band >= 0 && band < AUD_EQ_NBANDS); - eq_slider_set_val (equalizerwin_bands[band], value); - equalizerwin_eq_changed(); -} - -static float equalizerwin_get_preamp (void) -{ - return eq_slider_get_val (equalizerwin_preamp); -} - -static float equalizerwin_get_band (int band) -{ - g_return_val_if_fail(band >= 0 && band < AUD_EQ_NBANDS, 0.0); - return eq_slider_get_val (equalizerwin_bands[band]); -} - -static void load_auto_preset (const char * filename) -{ - char * eq_file = g_strconcat (filename, ".", EQUALIZER_DEFAULT_PRESET_EXT, nullptr); - gboolean success = equalizerwin_read_aud_preset (eq_file); - g_free (eq_file); - - if (success) - return; - - char * folder = g_path_get_dirname (filename); - eq_file = g_build_filename (folder, EQUALIZER_DEFAULT_DIR_PRESET, nullptr); - success = equalizerwin_read_aud_preset (eq_file); - - g_free (folder); - g_free (eq_file); - - if (success) - return; - - char * base = g_path_get_basename (filename); - - if (! equalizerwin_load_preset (equalizer_auto_presets, base)) - eq_preset_load_default (); - - g_free (base); -} - -static void playback_begin_cb (void *, void *) -{ - if (aud_get_bool (nullptr, "equalizer_autoload")) - load_auto_preset (aud_drct_get_filename ()); -} diff --git a/src/skins/ui_main.cc b/src/skins/ui_main.cc deleted file mode 100644 index bd87803..0000000 --- a/src/skins/ui_main.cc +++ /dev/null @@ -1,1352 +0,0 @@ -/* Audacious - Cross-platform multimedia player - * Copyright (C) 2005-2011 Audacious development team. - * - * BMP - Cross-platform multimedia player - * Copyright (C) 2003-2004 BMP development team. - * - * Based on XMMS: - * Copyright (C) 1998-2003 XMMS development team. - * - * 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; under version 3 of the License. - * - * 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 <http://www.gnu.org/licenses>. - * - * The Audacious team does not consider modular code linking to - * Audacious or using our public API to be a derived work. - */ - -#include <math.h> -#include <stdlib.h> -#include <string.h> -#include <sys/time.h> - -#include <gdk/gdkkeysyms.h> -#include <gtk/gtk.h> - -#include <libaudcore/audstrings.h> -#include <libaudcore/drct.h> -#include <libaudcore/i18n.h> -#include <libaudcore/plugins.h> -#include <libaudcore/runtime.h> -#include <libaudgui/libaudgui.h> - -#include "actions-mainwin.h" -#include "actions-playlist.h" -#include "dnd.h" -#include "menus.h" -#include "plugin.h" -#include "plugin-window.h" -#include "skins_cfg.h" -#include "ui_equalizer.h" -#include "ui_main.h" -#include "ui_main_evlisteners.h" -#include "ui_playlist.h" -#include "ui_skinned_button.h" -#include "ui_skinned_horizontal_slider.h" -#include "ui_skinned_menurow.h" -#include "ui_skinned_monostereo.h" -#include "ui_skinned_number.h" -#include "ui_skinned_playlist.h" -#include "ui_skinned_playstatus.h" -#include "ui_skinned_textbox.h" -#include "ui_skinned_window.h" -#include "ui_vis.h" -#include "util.h" -#include "view.h" - -#define SEEK_THRESHOLD 200 /* milliseconds */ -#define SEEK_TIMEOUT 100 /* milliseconds */ -#define SEEK_SPEED 50 /* milliseconds per pixel */ - -GtkWidget *mainwin = nullptr; - -static int balance; -static int seek_source = 0, seek_start, seek_time; - -static bool mainwin_info_text_locked = false; -static String mainwin_tb_old_text; - -static int status_message_source = 0; -static int mainwin_volume_release_timeout = 0; - -static GtkWidget *mainwin_menubtn, *mainwin_minimize, *mainwin_shade, *mainwin_close; -static GtkWidget *mainwin_shaded_menubtn, *mainwin_shaded_minimize, *mainwin_shaded_shade, *mainwin_shaded_close; - -static GtkWidget *mainwin_rew, *mainwin_fwd; -static GtkWidget *mainwin_eject; -static GtkWidget *mainwin_play, *mainwin_pause, *mainwin_stop; - -GtkWidget *mainwin_shuffle, *mainwin_repeat; -GtkWidget *mainwin_eq, *mainwin_pl; - -GtkWidget *mainwin_info; -GtkWidget *mainwin_stime_min, *mainwin_stime_sec; - -static GtkWidget *mainwin_rate_text, *mainwin_freq_text, *mainwin_othertext; - -GtkWidget *mainwin_playstatus; - -GtkWidget *mainwin_minus_num, *mainwin_10min_num, *mainwin_min_num; -GtkWidget *mainwin_10sec_num, *mainwin_sec_num; - -GtkWidget *mainwin_vis; -GtkWidget *mainwin_svis; - -GtkWidget *mainwin_sposition = nullptr; - -GtkWidget *mainwin_menurow; -static GtkWidget *mainwin_volume, *mainwin_balance; -GtkWidget *mainwin_position; - -static GtkWidget *mainwin_monostereo; -static GtkWidget *mainwin_srew, *mainwin_splay, *mainwin_spause; -static GtkWidget *mainwin_sstop, *mainwin_sfwd, *mainwin_seject, *mainwin_about; - -static void mainwin_position_motion_cb (void); -static void mainwin_position_release_cb (void); -static void mainwin_set_volume_diff (int diff); - -static void format_time (char buf[7], int time, int length) -{ - gboolean zero = aud_get_bool (nullptr, "leading_zero"); - gboolean remaining = aud_get_bool ("skins", "show_remaining_time"); - - if (remaining && length > 0) - { - time = (length - time) / 1000; - - if (time < 60) - snprintf (buf, 7, zero ? "-00:%02d" : " -0:%02d", time); - else if (time < 6000) - snprintf (buf, 7, zero ? "%03d:%02d" : "%3d:%02d", -time / 60, time % 60); - else - snprintf (buf, 7, "%3d:%02d", -time / 3600, time / 60 % 60); - } - else - { - time /= 1000; - - if (time < 6000) - snprintf (buf, 7, zero ? " %02d:%02d" : " %2d:%02d", time / 60, time % 60); - else if (time < 60000) - snprintf (buf, 7, "%3d:%02d", time / 60, time % 60); - else - snprintf (buf, 7, "%3d:%02d", time / 3600, time / 60 % 60); - } -} - -static void -mainwin_menubtn_cb(void) -{ - int x, y; - gtk_window_get_position(GTK_WINDOW(mainwin), &x, &y); - menu_popup (UI_MENU_MAIN, x + 6 * config.scale, - y + MAINWIN_SHADED_HEIGHT * config.scale, FALSE, FALSE, 1, GDK_CURRENT_TIME); -} - -static void mainwin_minimize_cb (void) -{ - if (!mainwin) - return; - - gtk_window_iconify(GTK_WINDOW(mainwin)); -} - -static void -mainwin_shade_toggle(void) -{ - view_set_player_shaded (! aud_get_bool ("skins", "player_shaded")); -} - -static void mainwin_lock_info_text (const char * text) -{ - GtkWidget * textbox = - active_skin->properties.mainwin_othertext_is_status ? - mainwin_othertext : mainwin_info; - - if (! mainwin_info_text_locked) - mainwin_tb_old_text = String (textbox_get_text (textbox)); - - mainwin_info_text_locked = true; - textbox_set_text (textbox, text); -} - -static void mainwin_release_info_text (void) -{ - if (! mainwin_info_text_locked) - return; - - if (active_skin->properties.mainwin_othertext_is_status) - textbox_set_text (mainwin_othertext, mainwin_tb_old_text); - else - textbox_set_text (mainwin_info, mainwin_tb_old_text); - - mainwin_info_text_locked = false; - mainwin_tb_old_text = String (); -} - -static void mainwin_set_info_text (const char * text) -{ - if (mainwin_info_text_locked && ! active_skin->properties.mainwin_othertext_is_status) - mainwin_tb_old_text = String (text); - else - textbox_set_text (mainwin_info, text); -} - -static void mainwin_set_othertext (const char * text) -{ - if (mainwin_info_text_locked && active_skin->properties.mainwin_othertext_is_status) - mainwin_tb_old_text = String (text); - else - textbox_set_text (mainwin_othertext, text); -} - -static gboolean clear_status_message (void *) -{ - mainwin_release_info_text (); - status_message_source = 0; - return G_SOURCE_REMOVE; -} - -void mainwin_show_status_message (const char * message) -{ - if (status_message_source) - g_source_remove (status_message_source); - - mainwin_lock_info_text (message); - status_message_source = g_timeout_add (1000, clear_status_message, nullptr); -} - -static char * -make_mainwin_title(const char * title) -{ - if (title != nullptr) - return g_strdup_printf(_("%s - Audacious"), title); - else - return g_strdup(_("Audacious")); -} - -void -mainwin_set_song_title(const char * title) -{ - char *mainwin_title_text = make_mainwin_title(title); - gtk_window_set_title(GTK_WINDOW(mainwin), mainwin_title_text); - g_free(mainwin_title_text); - - mainwin_set_info_text (title ? title : ""); -} - -static void setup_widget (GtkWidget * widget, int x, int y, gboolean show) -{ - /* leave no-show-all widgets alone (they are shown/hidden elsewhere) */ - if (! gtk_widget_get_no_show_all (widget)) - { - int width, height; - - /* use get_size_request(), not get_preferred_size() */ - /* get_preferred_size() will return 0x0 for hidden widgets */ - gtk_widget_get_size_request (widget, & width, & height); - - width /= config.scale; - height /= config.scale; - - /* hide widgets that are outside the window boundary */ - if (x < 0 || x + width > active_skin->properties.mainwin_width || - y < 0 || y + height > active_skin->properties.mainwin_height) - show = FALSE; - - gtk_widget_set_visible (widget, show); - } - - window_move_widget (mainwin, FALSE, widget, x, y); -} - -void mainwin_refresh_hints (void) -{ - const SkinProperties * p = & active_skin->properties; - - gtk_widget_set_visible (mainwin_menurow, p->mainwin_menurow_visible); - gtk_widget_set_visible (mainwin_rate_text, p->mainwin_streaminfo_visible); - gtk_widget_set_visible (mainwin_freq_text, p->mainwin_streaminfo_visible); - gtk_widget_set_visible (mainwin_monostereo, p->mainwin_streaminfo_visible); - - textbox_set_width (mainwin_info, p->mainwin_text_width); - - setup_widget (mainwin_vis, p->mainwin_vis_x, p->mainwin_vis_y, p->mainwin_vis_visible); - setup_widget (mainwin_info, p->mainwin_text_x, p->mainwin_text_y, p->mainwin_text_visible); - setup_widget (mainwin_othertext, p->mainwin_infobar_x, p->mainwin_infobar_y, p->mainwin_othertext_visible); - - setup_widget (mainwin_minus_num, p->mainwin_number_0_x, p->mainwin_number_0_y, TRUE); - setup_widget (mainwin_10min_num, p->mainwin_number_1_x, p->mainwin_number_1_y, TRUE); - setup_widget (mainwin_min_num, p->mainwin_number_2_x, p->mainwin_number_2_y, TRUE); - setup_widget (mainwin_10sec_num, p->mainwin_number_3_x, p->mainwin_number_3_y, TRUE); - setup_widget (mainwin_sec_num, p->mainwin_number_4_x, p->mainwin_number_4_y, TRUE); - setup_widget (mainwin_position, p->mainwin_position_x, p->mainwin_position_y, TRUE); - - setup_widget (mainwin_playstatus, p->mainwin_playstatus_x, p->mainwin_playstatus_y, TRUE); - setup_widget (mainwin_volume, p->mainwin_volume_x, p->mainwin_volume_y, TRUE); - setup_widget (mainwin_balance, p->mainwin_balance_x, p->mainwin_balance_y, TRUE); - setup_widget (mainwin_rew, p->mainwin_previous_x, p->mainwin_previous_y, TRUE); - setup_widget (mainwin_play, p->mainwin_play_x, p->mainwin_play_y, TRUE); - setup_widget (mainwin_pause, p->mainwin_pause_x, p->mainwin_pause_y, TRUE); - setup_widget (mainwin_stop, p->mainwin_stop_x, p->mainwin_stop_y, TRUE); - setup_widget (mainwin_fwd, p->mainwin_next_x, p->mainwin_next_y, TRUE); - setup_widget (mainwin_eject, p->mainwin_eject_x, p->mainwin_eject_y, TRUE); - setup_widget (mainwin_eq, p->mainwin_eqbutton_x, p->mainwin_eqbutton_y, TRUE); - setup_widget (mainwin_pl, p->mainwin_plbutton_x, p->mainwin_plbutton_y, TRUE); - setup_widget (mainwin_shuffle, p->mainwin_shuffle_x, p->mainwin_shuffle_y, TRUE); - setup_widget (mainwin_repeat, p->mainwin_repeat_x, p->mainwin_repeat_y, TRUE); - setup_widget (mainwin_about, p->mainwin_about_x, p->mainwin_about_y, TRUE); - setup_widget (mainwin_minimize, p->mainwin_minimize_x, p->mainwin_minimize_y, TRUE); - setup_widget (mainwin_shade, p->mainwin_shade_x, p->mainwin_shade_y, TRUE); - setup_widget (mainwin_close, p->mainwin_close_x, p->mainwin_close_y, TRUE); - - if (aud_get_bool ("skins", "player_shaded")) - window_set_size (mainwin, MAINWIN_SHADED_WIDTH, MAINWIN_SHADED_HEIGHT); - else - window_set_size (mainwin, p->mainwin_width, p->mainwin_height); -} - -/* note that the song info is not translated since it is displayed using - * the skinned bitmap font, which supports only the English alphabet */ -void mainwin_set_song_info (int bitrate, int samplerate, int channels) -{ - char scratch[32]; - int length; - - if (bitrate > 0) - { - if (bitrate < 1000000) - snprintf (scratch, sizeof scratch, "%3d", bitrate / 1000); - else - snprintf (scratch, sizeof scratch, "%2dH", bitrate / 100000); - - textbox_set_text (mainwin_rate_text, scratch); - } - else - textbox_set_text (mainwin_rate_text, ""); - - if (samplerate > 0) - { - snprintf (scratch, sizeof scratch, "%2d", samplerate / 1000); - textbox_set_text (mainwin_freq_text, scratch); - } - else - textbox_set_text (mainwin_freq_text, ""); - - ui_skinned_monostereo_set_num_channels (mainwin_monostereo, channels); - - if (bitrate > 0) - snprintf (scratch, sizeof scratch, "%d kbps", bitrate / 1000); - else - scratch[0] = 0; - - if (samplerate > 0) - { - length = strlen (scratch); - snprintf (scratch + length, sizeof scratch - length, "%s%d kHz", length ? - ", " : "", samplerate / 1000); - } - - if (channels > 0) - { - length = strlen (scratch); - snprintf (scratch + length, sizeof scratch - length, "%s%s", length ? - ", " : "", channels > 2 ? "surround" : channels > 1 ? "stereo" : "mono"); - } - - mainwin_set_othertext (scratch); -} - -void -mainwin_clear_song_info(void) -{ - mainwin_set_song_title (nullptr); - - ui_vis_clear_data (mainwin_vis); - ui_svis_clear_data (mainwin_svis); - - gtk_widget_hide (mainwin_minus_num); - gtk_widget_hide (mainwin_10min_num); - gtk_widget_hide (mainwin_min_num); - gtk_widget_hide (mainwin_10sec_num); - gtk_widget_hide (mainwin_sec_num); - gtk_widget_hide (mainwin_stime_min); - gtk_widget_hide (mainwin_stime_sec); - gtk_widget_hide (mainwin_position); - gtk_widget_hide (mainwin_sposition); - - hslider_set_pressed (mainwin_position, FALSE); - hslider_set_pressed (mainwin_sposition, FALSE); - - /* clear sampling parameter displays */ - textbox_set_text (mainwin_rate_text, " "); - textbox_set_text (mainwin_freq_text, " "); - ui_skinned_monostereo_set_num_channels(mainwin_monostereo, 0); - mainwin_set_othertext (""); - - if (mainwin_playstatus != nullptr) - ui_skinned_playstatus_set_status(mainwin_playstatus, STATUS_STOP); - - playlistwin_hide_timer(); -} - -void -mainwin_disable_seekbar(void) -{ - if (!mainwin) - return; - - gtk_widget_hide(mainwin_position); - gtk_widget_hide(mainwin_sposition); -} - -static void mainwin_scrolled (GtkWidget * widget, GdkEventScroll * event, void * - unused) -{ - switch (event->direction) { - case GDK_SCROLL_UP: - mainwin_set_volume_diff (5); - break; - case GDK_SCROLL_DOWN: - mainwin_set_volume_diff (-5); - break; - case GDK_SCROLL_LEFT: - aud_drct_seek (aud_drct_get_time () - 5000); - break; - case GDK_SCROLL_RIGHT: - aud_drct_seek (aud_drct_get_time () + 5000); - break; - default: - break; - } -} - -static gboolean -mainwin_mouse_button_press(GtkWidget * widget, - GdkEventButton * event, - void * callback_data) -{ - if (event->button == 1 && event->type == GDK_2BUTTON_PRESS && - event->window == gtk_widget_get_window (widget)&& - event->y < 14 * config.scale) - { - mainwin_shade_toggle (); - return TRUE; - } - - if (event->button == 3) - { - menu_popup (UI_MENU_MAIN, event->x_root, event->y_root, FALSE, FALSE, - event->button, event->time); - return TRUE; - } - - return FALSE; -} - -static void mainwin_playback_rpress (GtkWidget * button, GdkEventButton * event) -{ - menu_popup (UI_MENU_PLAYBACK, event->x_root, event->y_root, FALSE, FALSE, - event->button, event->time); -} - -gboolean mainwin_keypress (GtkWidget * widget, GdkEventKey * event, - void * unused) -{ - if (ui_skinned_playlist_key (playlistwin_list, event)) - return 1; - - switch (event->keyval) - { - case GDK_KEY_minus: - mainwin_set_volume_diff (-5); - break; - case GDK_KEY_plus: - mainwin_set_volume_diff (5); - break; - case GDK_KEY_Left: - case GDK_KEY_KP_Left: - case GDK_KEY_KP_7: - aud_drct_seek (aud_drct_get_time () - 5000); - break; - case GDK_KEY_Right: - case GDK_KEY_KP_Right: - case GDK_KEY_KP_9: - aud_drct_seek (aud_drct_get_time () + 5000); - break; - case GDK_KEY_KP_4: - aud_drct_pl_prev (); - break; - case GDK_KEY_KP_6: - aud_drct_pl_next (); - break; - case GDK_KEY_KP_Insert: - audgui_jump_to_track (); - break; - case GDK_KEY_space: - aud_drct_pause(); - break; - case GDK_KEY_Tab: /* GtkUIManager does not handle tab, apparently. */ - if (event->state & GDK_SHIFT_MASK) - action_playlist_prev (); - else - action_playlist_next (); - - break; - case GDK_KEY_ISO_Left_Tab: - action_playlist_prev (); - break; - default: - return FALSE; - } - - return TRUE; -} - -/* - * Rewritten 09/13/06: - * - * Remove all of this flaky iter/sourcelist/strsplit stuff. - * All we care about is the filepath. - * - * We can figure this out and easily pass it to g_filename_from_uri(). - * - nenolod - */ -void -mainwin_drag_data_received(GtkWidget * widget, - GdkDragContext * context, - int x, - int y, - GtkSelectionData * selection_data, - unsigned info, - unsigned time, - void * user_data) -{ - g_return_if_fail(selection_data != nullptr); - - const char * data = (const char *) gtk_selection_data_get_data - (selection_data); - g_return_if_fail (data); - - if (str_has_prefix_nocase (data, "file:///")) - { - if (str_has_suffix_nocase (data, ".wsz\r\n") || str_has_suffix_nocase - (data, ".zip\r\n")) - { - on_skin_view_drag_data_received (0, context, x, y, selection_data, info, time, 0); - return; - } - } - - audgui_urilist_open (data); -} - -static int time_now (void) -{ - struct timeval tv; - gettimeofday (& tv, nullptr); - return (tv.tv_sec % (24 * 3600) * 1000 + tv.tv_usec / 1000); -} - -static int time_diff (int a, int b) -{ - if (a > 18 * 3600 * 1000 && b < 6 * 3600 * 1000) /* detect midnight */ - b += 24 * 3600 * 1000; - return (b > a) ? b - a : 0; -} - -static gboolean seek_timeout (void * rewind) -{ - if (! aud_drct_get_playing ()) - { - seek_source = 0; - return G_SOURCE_REMOVE; - } - - int held = time_diff (seek_time, time_now ()); - if (held < SEEK_THRESHOLD) - return G_SOURCE_CONTINUE; - - int position; - if (GPOINTER_TO_INT (rewind)) - position = seek_start - held / SEEK_SPEED; - else - position = seek_start + held / SEEK_SPEED; - - position = aud::clamp (position, 0, 219); - hslider_set_pos (mainwin_position, position); - mainwin_position_motion_cb (); - - return G_SOURCE_CONTINUE; -} - -static gboolean seek_press (GtkWidget * widget, GdkEventButton * event, - gboolean rewind) -{ - if (event->button != 1 || seek_source) - return FALSE; - - seek_start = hslider_get_pos (mainwin_position); - seek_time = time_now (); - seek_source = g_timeout_add (SEEK_TIMEOUT, seek_timeout, GINT_TO_POINTER (rewind)); - return FALSE; -} - -static gboolean seek_release (GtkWidget * widget, GdkEventButton * event, - gboolean rewind) -{ - if (event->button != 1 || ! seek_source) - return FALSE; - - if (! aud_drct_get_playing () || time_diff (seek_time, time_now ()) < - SEEK_THRESHOLD) - { - if (rewind) - aud_drct_pl_prev (); - else - aud_drct_pl_next (); - } - else - mainwin_position_release_cb (); - - g_source_remove (seek_source); - seek_source = 0; - return FALSE; -} - -static void mainwin_rew_press (GtkWidget * button, GdkEventButton * event) - {seek_press (button, event, TRUE); } -static void mainwin_rew_release (GtkWidget * button, GdkEventButton * event) - {seek_release (button, event, TRUE); } -static void mainwin_fwd_press (GtkWidget * button, GdkEventButton * event) - {seek_press (button, event, FALSE); } -static void mainwin_fwd_release (GtkWidget * button, GdkEventButton * event) - {seek_release (button, event, FALSE); } - -static void mainwin_shuffle_cb (GtkWidget * button, GdkEventButton * event) - {aud_set_bool (nullptr, "shuffle", button_get_active (button)); } -static void mainwin_repeat_cb (GtkWidget * button, GdkEventButton * event) - {aud_set_bool (nullptr, "repeat", button_get_active (button)); } -static void mainwin_eq_cb (GtkWidget * button, GdkEventButton * event) - {view_set_show_equalizer (button_get_active (button)); } -static void mainwin_pl_cb (GtkWidget * button, GdkEventButton * event) - {view_set_show_playlist (button_get_active (button)); } - -static void mainwin_spos_set_knob (void) -{ - int pos = hslider_get_pos (mainwin_sposition); - - int x; - if (pos < 6) - x = 17; - else if (pos < 9) - x = 20; - else - x = 23; - - hslider_set_knob (mainwin_sposition, x, 36, x, 36); -} - -static void mainwin_spos_motion_cb (void) -{ - mainwin_spos_set_knob (); - - int pos = hslider_get_pos (mainwin_sposition); - int length = aud_drct_get_length (); - int time = (pos - 1) * length / 12; - - char buf[7]; - format_time (buf, time, length); - - textbox_set_text (mainwin_stime_min, buf); - textbox_set_text (mainwin_stime_sec, buf + 4); -} - -static void mainwin_spos_release_cb (void) -{ - mainwin_spos_set_knob (); - - int pos = hslider_get_pos (mainwin_sposition); - aud_drct_seek (aud_drct_get_length () * (pos - 1) / 12); -} - -static void mainwin_position_motion_cb (void) -{ - int length = aud_drct_get_length () / 1000; - int pos = hslider_get_pos (mainwin_position); - int time = pos * length / 219; - - char * seek_msg = g_strdup_printf (_("Seek to %d:%-2.2d / %d:%-2.2d"), time - / 60, time % 60, length / 60, length % 60); - mainwin_lock_info_text(seek_msg); - g_free(seek_msg); -} - -static void mainwin_position_release_cb (void) -{ - int length = aud_drct_get_length (); - int pos = hslider_get_pos (mainwin_position); - int time = (int64_t) pos * length / 219; - - aud_drct_seek(time); - mainwin_release_info_text(); -} - -void -mainwin_adjust_volume_motion(int v) -{ - char *volume_msg; - - volume_msg = g_strdup_printf(_("Volume: %d%%"), v); - mainwin_lock_info_text(volume_msg); - g_free(volume_msg); - - aud_drct_set_volume_main (v); - aud_drct_set_volume_balance (balance); -} - -void -mainwin_adjust_volume_release(void) -{ - mainwin_release_info_text(); -} - -void -mainwin_adjust_balance_motion(int b) -{ - char *balance_msg; - - balance = b; - aud_drct_set_volume_balance (b); - - if (b < 0) - balance_msg = g_strdup_printf(_("Balance: %d%% left"), -b); - else if (b == 0) - balance_msg = g_strdup_printf(_("Balance: center")); - else - balance_msg = g_strdup_printf(_("Balance: %d%% right"), b); - - mainwin_lock_info_text(balance_msg); - g_free(balance_msg); -} - -void -mainwin_adjust_balance_release(void) -{ - mainwin_release_info_text(); -} - -static void mainwin_volume_set_frame (void) -{ - int pos = hslider_get_pos (mainwin_volume); - int frame = (pos * 27 + 25) / 51; - hslider_set_frame (mainwin_volume, 0, 15 * frame); -} - -void mainwin_set_volume_slider (int percent) -{ - hslider_set_pos (mainwin_volume, (percent * 51 + 50) / 100); - mainwin_volume_set_frame (); -} - -static void mainwin_volume_motion_cb (void) -{ - mainwin_volume_set_frame (); - int pos = hslider_get_pos (mainwin_volume); - int vol = (pos * 100 + 25) / 51; - - mainwin_adjust_volume_motion(vol); - equalizerwin_set_volume_slider(vol); -} - -static void mainwin_volume_release_cb (void) -{ - mainwin_volume_set_frame (); - mainwin_adjust_volume_release(); -} - -static gboolean mainwin_volume_timeout_cb (void *) -{ - mainwin_volume_release_cb (); - mainwin_volume_release_timeout = 0; - return G_SOURCE_REMOVE; -} - -static void mainwin_balance_set_frame (void) -{ - int pos = hslider_get_pos (mainwin_balance); - int frame = (abs (pos - 12) * 27 + 6) / 12; - hslider_set_frame (mainwin_balance, 9, 15 * frame); -} - -void mainwin_set_balance_slider (int percent) -{ - if (percent > 0) - hslider_set_pos (mainwin_balance, 12 + (percent * 12 + 50) / 100); - else - hslider_set_pos (mainwin_balance, 12 + (percent * 12 - 50) / 100); - - mainwin_balance_set_frame (); -} - -static void mainwin_balance_motion_cb (void) -{ - mainwin_balance_set_frame (); - int pos = hslider_get_pos (mainwin_balance); - - int bal; - if (pos > 12) - bal = ((pos - 12) * 100 + 6) / 12; - else - bal = ((pos - 12) * 100 - 6) / 12; - - mainwin_adjust_balance_motion(bal); - equalizerwin_set_balance_slider(bal); -} - -static void mainwin_balance_release_cb (void) -{ - mainwin_balance_set_frame (); - mainwin_adjust_volume_release(); -} - -static void mainwin_set_volume_diff (int diff) -{ - int vol = aud_drct_get_volume_main (); - - vol = aud::clamp (vol + diff, 0, 100); - mainwin_adjust_volume_motion(vol); - mainwin_set_volume_slider(vol); - equalizerwin_set_volume_slider(vol); - - if (mainwin_volume_release_timeout) - g_source_remove(mainwin_volume_release_timeout); - mainwin_volume_release_timeout = - g_timeout_add(700, mainwin_volume_timeout_cb, nullptr); -} - -void mainwin_mr_change (MenuRowItem i) -{ - switch (i) - { - case MENUROW_OPTIONS: - mainwin_lock_info_text (_("Options Menu")); - break; - case MENUROW_ALWAYS: - if (aud_get_bool ("skins", "always_on_top")) - mainwin_lock_info_text (_("Disable 'Always On Top'")); - else - mainwin_lock_info_text (_("Enable 'Always On Top'")); - break; - case MENUROW_FILEINFOBOX: - mainwin_lock_info_text (_("File Info Box")); - break; - case MENUROW_SCALE: - mainwin_lock_info_text (_("Double Size")); - break; - case MENUROW_VISUALIZATION: - mainwin_lock_info_text (_("Visualizations")); - break; - default: - break; - } -} - -void mainwin_mr_release (MenuRowItem i, GdkEventButton * event) -{ - switch (i) - { - case MENUROW_OPTIONS: - menu_popup (UI_MENU_VIEW, event->x_root, event->y_root, FALSE, FALSE, 1, event->time); - break; - case MENUROW_ALWAYS: - view_set_on_top (! aud_get_bool ("skins", "always_on_top")); - break; - case MENUROW_FILEINFOBOX: - audgui_infowin_show_current (); - break; - case MENUROW_SCALE: - view_set_double_size (! aud_get_bool ("skins", "double_size")); - break; - case MENUROW_VISUALIZATION: - audgui_show_prefs_for_plugin_type (PluginType::Vis); - break; - default: - break; - } - - mainwin_release_info_text(); -} - -gboolean -change_timer_mode_cb(GtkWidget *widget, GdkEventButton *event) -{ - if (event->button == 1) - view_set_show_remaining (! aud_get_bool ("skins", "show_remaining_time")); - else if (event->button == 3) - return FALSE; - - return TRUE; -} - -static gboolean mainwin_info_button_press (GtkWidget * widget, GdkEventButton * - event) -{ - if (event->type == GDK_BUTTON_PRESS && event->button == 3) - { - menu_popup (UI_MENU_PLAYBACK, event->x_root, event->y_root, FALSE, - FALSE, event->button, event->time); - return TRUE; - } - - if (event->type == GDK_2BUTTON_PRESS && event->button == 1) - { - audgui_infowin_show_current (); - return TRUE; - } - - return FALSE; -} - -static void -mainwin_create_widgets(void) -{ - mainwin_menubtn = button_new (9, 9, 0, 0, 0, 9, SKIN_TITLEBAR, SKIN_TITLEBAR); - window_put_widget (mainwin, FALSE, mainwin_menubtn, 6, 3); - button_on_release (mainwin_menubtn, (ButtonCB) mainwin_menubtn_cb); - - mainwin_minimize = button_new (9, 9, 9, 0, 9, 9, SKIN_TITLEBAR, SKIN_TITLEBAR); - window_put_widget (mainwin, FALSE, mainwin_minimize, 244, 3); - button_on_release (mainwin_minimize, (ButtonCB) mainwin_minimize_cb); - - mainwin_shade = button_new (9, 9, 0, 18, 9, 18, SKIN_TITLEBAR, SKIN_TITLEBAR); - window_put_widget (mainwin, FALSE, mainwin_shade, 254, 3); - button_on_release (mainwin_shade, (ButtonCB) mainwin_shade_toggle); - - mainwin_close = button_new (9, 9, 18, 0, 18, 9, SKIN_TITLEBAR, SKIN_TITLEBAR); - window_put_widget (mainwin, FALSE, mainwin_close, 264, 3); - button_on_release (mainwin_close, (ButtonCB) handle_window_close); - - mainwin_rew = button_new (23, 18, 0, 0, 0, 18, SKIN_CBUTTONS, SKIN_CBUTTONS); - window_put_widget (mainwin, FALSE, mainwin_rew, 16, 88); - button_on_press (mainwin_rew, mainwin_rew_press); - button_on_release (mainwin_rew, mainwin_rew_release); - button_on_rpress (mainwin_rew, mainwin_playback_rpress); - - mainwin_fwd = button_new (22, 18, 92, 0, 92, 18, SKIN_CBUTTONS, SKIN_CBUTTONS); - window_put_widget (mainwin, FALSE, mainwin_fwd, 108, 88); - button_on_press (mainwin_fwd, mainwin_fwd_press); - button_on_release (mainwin_fwd, mainwin_fwd_release); - button_on_rpress (mainwin_fwd, mainwin_playback_rpress); - - mainwin_play = button_new (23, 18, 23, 0, 23, 18, SKIN_CBUTTONS, SKIN_CBUTTONS); - window_put_widget (mainwin, FALSE, mainwin_play, 39, 88); - button_on_release (mainwin_play, (ButtonCB) aud_drct_play); - button_on_rpress (mainwin_play, mainwin_playback_rpress); - - mainwin_pause = button_new (23, 18, 46, 0, 46, 18, SKIN_CBUTTONS, SKIN_CBUTTONS); - window_put_widget (mainwin, FALSE, mainwin_pause, 62, 88); - button_on_release (mainwin_pause, (ButtonCB) aud_drct_pause); - button_on_rpress (mainwin_pause, mainwin_playback_rpress); - - mainwin_stop = button_new (23, 18, 69, 0, 69, 18, SKIN_CBUTTONS, SKIN_CBUTTONS); - window_put_widget (mainwin, FALSE, mainwin_stop, 85, 88); - button_on_release (mainwin_stop, (ButtonCB) aud_drct_stop); - button_on_rpress (mainwin_stop, mainwin_playback_rpress); - - mainwin_eject = button_new (22, 16, 114, 0, 114, 16, SKIN_CBUTTONS, SKIN_CBUTTONS); - window_put_widget (mainwin, FALSE, mainwin_eject, 136, 89); - button_on_release (mainwin_eject, (ButtonCB) action_play_file); - - mainwin_shuffle = button_new_toggle (46, 15, 28, 0, 28, 15, 28, 30, 28, 45, SKIN_SHUFREP, SKIN_SHUFREP); - window_put_widget (mainwin, FALSE, mainwin_shuffle, 164, 89); - button_set_active (mainwin_shuffle, aud_get_bool (nullptr, "shuffle")); - button_on_release (mainwin_shuffle, mainwin_shuffle_cb); - - mainwin_repeat = button_new_toggle (28, 15, 0, 0, 0, 15, 0, 30, 0, 45, SKIN_SHUFREP, SKIN_SHUFREP); - window_put_widget (mainwin, FALSE, mainwin_repeat, 210, 89); - button_set_active (mainwin_repeat, aud_get_bool (nullptr, "repeat")); - button_on_release (mainwin_repeat, mainwin_repeat_cb); - - mainwin_eq = button_new_toggle (23, 12, 0, 61, 46, 61, 0, 73, 46, 73, SKIN_SHUFREP, SKIN_SHUFREP); - window_put_widget (mainwin, FALSE, mainwin_eq, 219, 58); - button_on_release (mainwin_eq, mainwin_eq_cb); - - mainwin_pl = button_new_toggle (23, 12, 23, 61, 69, 61, 23, 73, 69, 73, SKIN_SHUFREP, SKIN_SHUFREP); - window_put_widget (mainwin, FALSE, mainwin_pl, 242, 58); - button_on_release (mainwin_pl, mainwin_pl_cb); - - String font = aud_get_str ("skins", "mainwin_font"); - mainwin_info = textbox_new (153, "", config.mainwin_use_bitmapfont ? nullptr : - (const char *) font, config.autoscroll); - - window_put_widget (mainwin, FALSE, mainwin_info, 112, 27); - g_signal_connect (mainwin_info, "button-press-event", (GCallback) - mainwin_info_button_press, nullptr); - - mainwin_othertext = textbox_new (153, "", nullptr, FALSE); - window_put_widget (mainwin, FALSE, mainwin_othertext, 112, 43); - - mainwin_rate_text = textbox_new (15, "", nullptr, FALSE); - window_put_widget (mainwin, FALSE, mainwin_rate_text, 111, 43); - - mainwin_freq_text = textbox_new (10, "", nullptr, FALSE); - window_put_widget (mainwin, FALSE, mainwin_freq_text, 156, 43); - - mainwin_menurow = ui_skinned_menurow_new (); - window_put_widget (mainwin, FALSE, mainwin_menurow, 10, 22); - - mainwin_volume = hslider_new (0, 51, SKIN_VOLUME, 68, 13, 0, 0, 14, 11, 15, 422, 0, 422); - window_put_widget (mainwin, FALSE, mainwin_volume, 107, 57); - hslider_on_motion (mainwin_volume, mainwin_volume_motion_cb); - hslider_on_release (mainwin_volume, mainwin_volume_release_cb); - - mainwin_balance = hslider_new (0, 24, SKIN_BALANCE, 38, 13, 9, 0, 14, 11, 15, 422, 0, 422); - window_put_widget (mainwin, FALSE, mainwin_balance, 177, 57); - hslider_on_motion (mainwin_balance, mainwin_balance_motion_cb); - hslider_on_release (mainwin_balance, mainwin_balance_release_cb); - - mainwin_monostereo = ui_skinned_monostereo_new (); - window_put_widget (mainwin, FALSE, mainwin_monostereo, 212, 41); - - mainwin_playstatus = ui_skinned_playstatus_new (); - window_put_widget (mainwin, FALSE, mainwin_playstatus, 24, 28); - - mainwin_minus_num = ui_skinned_number_new (); - window_put_widget (mainwin, FALSE, mainwin_minus_num, 36, 26); - g_signal_connect(mainwin_minus_num, "button-press-event", G_CALLBACK(change_timer_mode_cb), nullptr); - - mainwin_10min_num = ui_skinned_number_new (); - window_put_widget (mainwin, FALSE, mainwin_10min_num, 48, 26); - g_signal_connect(mainwin_10min_num, "button-press-event", G_CALLBACK(change_timer_mode_cb), nullptr); - - mainwin_min_num = ui_skinned_number_new (); - window_put_widget (mainwin, FALSE, mainwin_min_num, 60, 26); - g_signal_connect(mainwin_min_num, "button-press-event", G_CALLBACK(change_timer_mode_cb), nullptr); - - mainwin_10sec_num = ui_skinned_number_new (); - window_put_widget (mainwin, FALSE, mainwin_10sec_num, 78, 26); - g_signal_connect(mainwin_10sec_num, "button-press-event", G_CALLBACK(change_timer_mode_cb), nullptr); - - mainwin_sec_num = ui_skinned_number_new (); - window_put_widget (mainwin, FALSE, mainwin_sec_num, 90, 26); - g_signal_connect(mainwin_sec_num, "button-press-event", G_CALLBACK(change_timer_mode_cb), nullptr); - - mainwin_about = button_new_small (20, 25); - window_put_widget (mainwin, FALSE, mainwin_about, 247, 83); - button_on_release (mainwin_about, (ButtonCB) audgui_show_about_window); - - mainwin_vis = ui_vis_new (); - window_put_widget (mainwin, FALSE, mainwin_vis, 24, 43); - - mainwin_position = hslider_new (0, 219, SKIN_POSBAR, 248, 10, 0, 0, 29, 10, 248, 0, 278, 0); - window_put_widget (mainwin, FALSE, mainwin_position, 16, 72); - hslider_on_motion (mainwin_position, mainwin_position_motion_cb); - hslider_on_release (mainwin_position, mainwin_position_release_cb); - - /* shaded */ - - mainwin_shaded_menubtn = button_new (9, 9, 0, 0, 0, 9, SKIN_TITLEBAR, SKIN_TITLEBAR); - window_put_widget (mainwin, TRUE, mainwin_shaded_menubtn, 6, 3); - button_on_release (mainwin_shaded_menubtn, (ButtonCB) mainwin_menubtn_cb); - - mainwin_shaded_minimize = button_new (9, 9, 9, 0, 9, 9, SKIN_TITLEBAR, SKIN_TITLEBAR); - window_put_widget (mainwin, TRUE, mainwin_shaded_minimize, 244, 3); - button_on_release (mainwin_shaded_minimize, (ButtonCB) mainwin_minimize_cb); - - mainwin_shaded_shade = button_new (9, 9, 0, 27, 9, 27, SKIN_TITLEBAR, SKIN_TITLEBAR); - window_put_widget (mainwin, TRUE, mainwin_shaded_shade, 254, 3); - button_on_release (mainwin_shaded_shade, (ButtonCB) mainwin_shade_toggle); - - mainwin_shaded_close = button_new (9, 9, 18, 0, 18, 9, SKIN_TITLEBAR, SKIN_TITLEBAR); - window_put_widget (mainwin, TRUE, mainwin_shaded_close, 264, 3); - button_on_release (mainwin_shaded_close, (ButtonCB) handle_window_close); - - mainwin_srew = button_new_small (8, 7); - window_put_widget (mainwin, TRUE, mainwin_srew, 169, 4); - button_on_release (mainwin_srew, (ButtonCB) aud_drct_pl_prev); - - mainwin_splay = button_new_small (10, 7); - window_put_widget (mainwin, TRUE, mainwin_splay, 177, 4); - button_on_release (mainwin_splay, (ButtonCB) aud_drct_play); - - mainwin_spause = button_new_small (10, 7); - window_put_widget (mainwin, TRUE, mainwin_spause, 187, 4); - button_on_release (mainwin_spause, (ButtonCB) aud_drct_pause); - - mainwin_sstop = button_new_small (9, 7); - window_put_widget (mainwin, TRUE, mainwin_sstop, 197, 4); - button_on_release (mainwin_sstop, (ButtonCB) aud_drct_stop); - - mainwin_sfwd = button_new_small (8, 7); - window_put_widget (mainwin, TRUE, mainwin_sfwd, 206, 4); - button_on_release (mainwin_sfwd, (ButtonCB) aud_drct_pl_next); - - mainwin_seject = button_new_small (9, 7); - window_put_widget (mainwin, TRUE, mainwin_seject, 216, 4); - button_on_release (mainwin_seject, (ButtonCB) action_play_file); - - mainwin_svis = ui_svis_new (); - window_put_widget (mainwin, TRUE, mainwin_svis, 79, 5); - - mainwin_sposition = hslider_new (1, 13, SKIN_TITLEBAR, 17, 7, 0, 36, 3, 7, 17, 36, 17, 36); - window_put_widget (mainwin, TRUE, mainwin_sposition, 226, 4); - hslider_on_motion (mainwin_sposition, mainwin_spos_motion_cb); - hslider_on_release (mainwin_sposition, mainwin_spos_release_cb); - - mainwin_stime_min = textbox_new (15, "", nullptr, FALSE); - window_put_widget (mainwin, TRUE, mainwin_stime_min, 130, 4); - - mainwin_stime_sec = textbox_new (10, "", nullptr, FALSE); - window_put_widget (mainwin, TRUE, mainwin_stime_sec, 147, 4); - - g_signal_connect(mainwin_stime_min, "button-press-event", G_CALLBACK(change_timer_mode_cb), nullptr); - g_signal_connect(mainwin_stime_sec, "button-press-event", G_CALLBACK(change_timer_mode_cb), nullptr); -} - -static void show_widgets (void) -{ - gtk_widget_set_no_show_all (mainwin_minus_num, TRUE); - gtk_widget_set_no_show_all (mainwin_10min_num, TRUE); - gtk_widget_set_no_show_all (mainwin_min_num, TRUE); - gtk_widget_set_no_show_all (mainwin_10sec_num, TRUE); - gtk_widget_set_no_show_all (mainwin_sec_num, TRUE); - gtk_widget_set_no_show_all (mainwin_stime_min, TRUE); - gtk_widget_set_no_show_all (mainwin_stime_sec, TRUE); - gtk_widget_set_no_show_all (mainwin_position, TRUE); - gtk_widget_set_no_show_all (mainwin_sposition, TRUE); - - window_set_shaded (mainwin, aud_get_bool ("skins", "player_shaded")); - window_show_all (mainwin); -} - -static gboolean state_cb (GtkWidget * widget, GdkEventWindowState * event, - void * unused) -{ - if (event->changed_mask & GDK_WINDOW_STATE_STICKY) - view_set_sticky (!! (event->new_window_state & GDK_WINDOW_STATE_STICKY)); - - if (event->changed_mask & GDK_WINDOW_STATE_ABOVE) - view_set_on_top (!! (event->new_window_state & GDK_WINDOW_STATE_ABOVE)); - - return TRUE; -} - -static void mainwin_draw (GtkWidget * window, cairo_t * cr) -{ - gboolean shaded = aud_get_bool ("skins", "player_shaded"); - int width = shaded ? MAINWIN_SHADED_WIDTH : active_skin->properties.mainwin_width; - int height = shaded ? MAINWIN_SHADED_HEIGHT : active_skin->properties.mainwin_height; - - skin_draw_pixbuf (cr, SKIN_MAIN, 0, 0, 0, 0, width, height); - skin_draw_mainwin_titlebar (cr, shaded, TRUE); -} - -static void -mainwin_create_window(void) -{ - gboolean shaded = aud_get_bool ("skins", "player_shaded"); - int width = shaded ? MAINWIN_SHADED_WIDTH : active_skin->properties.mainwin_width; - int height = shaded ? MAINWIN_SHADED_HEIGHT : active_skin->properties.mainwin_height; - - mainwin = window_new (& config.player_x, & config.player_y, width, height, - TRUE, shaded, mainwin_draw); - - gtk_window_set_title(GTK_WINDOW(mainwin), _("Audacious")); - - g_signal_connect(mainwin, "button_press_event", - G_CALLBACK(mainwin_mouse_button_press), nullptr); - g_signal_connect(mainwin, "scroll_event", - G_CALLBACK(mainwin_scrolled), nullptr); - - drag_dest_set(mainwin); - g_signal_connect ((GObject *) mainwin, "drag-data-received", (GCallback) - mainwin_drag_data_received, 0); - - g_signal_connect(mainwin, "key_press_event", - G_CALLBACK(mainwin_keypress), nullptr); - - ui_main_evlistener_init(); - - g_signal_connect ((GObject *) mainwin, "window-state-event", (GCallback) state_cb, nullptr); - g_signal_connect ((GObject *) mainwin, "delete-event", (GCallback) handle_window_close, nullptr); -} - -void mainwin_unhook (void) -{ - if (seek_source) - { - g_source_remove (seek_source); - seek_source = 0; - } - - if (status_message_source) - { - g_source_remove (status_message_source); - status_message_source = 0; - } - - if (mainwin_volume_release_timeout) - { - g_source_remove (mainwin_volume_release_timeout); - mainwin_volume_release_timeout = 0; - } - - ui_main_evlistener_dissociate (); - start_stop_visual (TRUE); - - mainwin_info_text_locked = false; - mainwin_tb_old_text = String (); -} - -void -mainwin_create(void) -{ - mainwin_create_window(); - - gtk_window_add_accel_group ((GtkWindow *) mainwin, menu_get_accel_group ()); - - mainwin_create_widgets(); - show_widgets (); -} - -static void mainwin_update_volume (void) -{ - int volume = aud_drct_get_volume_main (); - int balance = aud_drct_get_volume_balance (); - - mainwin_set_volume_slider (volume); - mainwin_set_balance_slider (balance); - equalizerwin_set_volume_slider (volume); - equalizerwin_set_balance_slider (balance); -} - -static void mainwin_update_time_display (int time, int length) -{ - char scratch[7]; - format_time (scratch, time, length); - - ui_skinned_number_set (mainwin_minus_num, scratch[0]); - ui_skinned_number_set (mainwin_10min_num, scratch[1]); - ui_skinned_number_set (mainwin_min_num, scratch[2]); - ui_skinned_number_set (mainwin_10sec_num, scratch[4]); - ui_skinned_number_set (mainwin_sec_num, scratch[5]); - - if (! hslider_get_pressed (mainwin_sposition)) - { - textbox_set_text (mainwin_stime_min, scratch); - textbox_set_text (mainwin_stime_sec, scratch + 4); - } - - playlistwin_set_time (scratch, scratch + 4); -} - -static void mainwin_update_time_slider (int time, int length) -{ - gtk_widget_set_visible (mainwin_position, length > 0); - gtk_widget_set_visible (mainwin_sposition, length > 0); - - if (length > 0 && seek_source == 0) - { - if (time < length) - { - hslider_set_pos (mainwin_position, time * (int64_t) 219 / length); - hslider_set_pos (mainwin_sposition, 1 + time * (int64_t) 12 / length); - } - else - { - hslider_set_pos (mainwin_position, 219); - hslider_set_pos (mainwin_sposition, 13); - } - - mainwin_spos_set_knob (); - } -} - -void mainwin_update_song_info (void) -{ - mainwin_update_volume (); - - if (! aud_drct_get_playing ()) - return; - - int time = 0, length = 0; - if (aud_drct_get_ready ()) - { - time = aud_drct_get_time (); - length = aud_drct_get_length (); - } - - mainwin_update_time_display (time, length); - mainwin_update_time_slider (time, length); -} - -/* actionentries actions */ - -void action_play_file (void) -{ - audgui_run_filebrowser(TRUE); /* TRUE = PLAY_BUTTON */ -} - -void action_play_location (void) -{ - audgui_show_add_url_window (TRUE); -} - -void action_playlist_manager (void) -{ - PluginHandle * manager = aud_plugin_lookup_basename ("playlist-manager"); - if (manager) - { - aud_plugin_enable (manager, true); - focus_plugin_window (manager); - } -} - -void action_search_tool (void) -{ - PluginHandle * search = aud_plugin_lookup_basename ("search-tool"); - if (search) - { - aud_plugin_enable (search, true); - focus_plugin_window (search); - } -} - -void action_ab_set (void) -{ - if (aud_drct_get_length () > 0) - { - int a, b; - aud_drct_get_ab_repeat (a, b); - - if (a < 0 || b >= 0) - { - a = aud_drct_get_time (); - b = -1; - mainwin_show_status_message (_("Repeat point A set.")); - } - else - { - b = aud_drct_get_time (); - mainwin_show_status_message (_("Repeat point B set.")); - } - - aud_drct_set_ab_repeat (a, b); - } -} - -void action_ab_clear (void) -{ - mainwin_show_status_message (_("Repeat points cleared.")); - aud_drct_set_ab_repeat (-1, -1); -} diff --git a/src/skins/ui_playlist.cc b/src/skins/ui_playlist.cc deleted file mode 100644 index 1eccd21..0000000 --- a/src/skins/ui_playlist.cc +++ /dev/null @@ -1,1163 +0,0 @@ -/* Audacious - Cross-platform multimedia player - * Copyright (C) 2005-2011 Audacious development team. - * - * BMP - Cross-platform multimedia player - * Copyright (C) 2003-2004 BMP development team. - * - * Based on XMMS: - * Copyright (C) 1998-2003 XMMS development team. - * - * 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; under version 3 of the License. - * - * 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 <http://www.gnu.org/licenses>. - * - * The Audacious team does not consider modular code linking to - * Audacious or using our public API to be a derived work. - */ - -#include <inttypes.h> -#include <string.h> - -#include <gdk/gdkkeysyms.h> -#include <gtk/gtk.h> - -#include <libaudcore/audstrings.h> -#include <libaudcore/drct.h> -#include <libaudcore/hook.h> -#include <libaudcore/i18n.h> -#include <libaudcore/playlist.h> -#include <libaudcore/runtime.h> -#include <libaudcore/tuple.h> -#include <libaudgui/libaudgui.h> - -#include "actions-mainwin.h" -#include "dnd.h" -#include "drag-handle.h" -#include "menus.h" -#include "plugin.h" -#include "skins_cfg.h" -#include "ui_main.h" -#include "ui_playlist.h" -#include "ui_skinned_button.h" -#include "ui_skinned_playlist.h" -#include "ui_skinned_playlist_slider.h" -#include "ui_skinned_textbox.h" -#include "ui_skinned_window.h" -#include "view.h" - -#define PLAYLISTWIN_MIN_WIDTH MAINWIN_WIDTH -#define PLAYLISTWIN_MIN_HEIGHT MAINWIN_HEIGHT -#define PLAYLISTWIN_WIDTH_SNAP 25 -#define PLAYLISTWIN_HEIGHT_SNAP 29 -#define PLAYLISTWIN_SHADED_HEIGHT MAINWIN_SHADED_HEIGHT - -#define APPEND(b, ...) snprintf (b + strlen (b), sizeof b - strlen (b), __VA_ARGS__) - -int active_playlist = -1, active_length = 0; -char * active_title = nullptr; - -GtkWidget * playlistwin, * playlistwin_list, * playlistwin_sinfo; - -static GtkWidget *playlistwin_shade, *playlistwin_close; -static GtkWidget *playlistwin_shaded_shade, *playlistwin_shaded_close; - -static GtkWidget *playlistwin_slider; -static GtkWidget *playlistwin_time_min, *playlistwin_time_sec; -static GtkWidget *playlistwin_info; -static GtkWidget *playlistwin_srew, *playlistwin_splay; -static GtkWidget *playlistwin_spause, *playlistwin_sstop; -static GtkWidget *playlistwin_sfwd, *playlistwin_seject; -static GtkWidget *playlistwin_sscroll_up, *playlistwin_sscroll_down; -static GtkWidget * resize_handle, * sresize_handle; -static GtkWidget * button_add, * button_sub, * button_sel, * button_misc, - * button_list; - -static void playlistwin_select_search_cbt_cb(GtkWidget *called_cbt, - void * other_cbt); -static gboolean playlistwin_select_search_kp_cb(GtkWidget *entry, - GdkEventKey *event, - void * searchdlg_win); - -static int resize_base_width, resize_base_height; -static int drop_position; -static gboolean song_changed; - -static void playlistwin_update_info (void) -{ - StringBuf s1 = str_format_time (aud_playlist_get_selected_length (active_playlist)); - StringBuf s2 = str_format_time (aud_playlist_get_total_length (active_playlist)); - textbox_set_text (playlistwin_info, str_concat ({s1, "/", s2})); -} - -static void update_rollup_text (void) -{ - int playlist = aud_playlist_get_active (); - int entry = aud_playlist_get_position (playlist); - Tuple tuple = aud_playlist_entry_get_tuple (playlist, entry, Playlist::Guess); - char scratch[512]; - - scratch[0] = 0; - - if (entry > -1) - { - String title = tuple.get_str (Tuple::FormattedTitle); - int length = tuple.get_int (Tuple::Length); - - if (aud_get_bool (nullptr, "show_numbers_in_pl")) - APPEND (scratch, "%d. ", 1 + entry); - - APPEND (scratch, "%s", (const char *) title); - - if (length >= 0) - { - StringBuf buf = str_format_time (length); - APPEND (scratch, " (%s)", (const char *) buf); - } - } - - textbox_set_text (playlistwin_sinfo, scratch); -} - -static void real_update (void) -{ - ui_skinned_playlist_update (playlistwin_list); - playlistwin_update_info (); - update_rollup_text (); -} - -void playlistwin_update (void) -{ - if (! aud_playlist_update_pending ()) - real_update (); -} - -static void -playlistwin_shade_toggle(void) -{ - view_set_playlist_shaded (! aud_get_bool ("skins", "playlist_shaded")); -} - -static void playlistwin_scroll (gboolean up) -{ - int rows, first; - - ui_skinned_playlist_row_info (playlistwin_list, & rows, & first); - ui_skinned_playlist_scroll_to (playlistwin_list, first + (up ? -1 : 1) * - rows / 3); -} - -static void playlistwin_scroll_up_pushed (void) -{ - playlistwin_scroll (TRUE); -} - -static void playlistwin_scroll_down_pushed (void) -{ - playlistwin_scroll (FALSE); -} - -static void -playlistwin_select_all(void) -{ - aud_playlist_select_all (active_playlist, 1); -} - -static void -playlistwin_select_none(void) -{ - aud_playlist_select_all (active_playlist, 0); -} - -static void copy_selected_to_new (int playlist) -{ - int entries = aud_playlist_entry_count (playlist); - int new_list = aud_playlist_count (); - Index<PlaylistAddItem> items; - int entry; - - aud_playlist_insert (new_list); - - for (entry = 0; entry < entries; entry ++) - { - if (aud_playlist_entry_get_selected (playlist, entry)) - { - items.append ( - aud_playlist_entry_get_filename (playlist, entry), - aud_playlist_entry_get_tuple (playlist, entry, Playlist::Guess) - ); - } - } - - aud_playlist_entry_insert_batch (new_list, 0, std::move (items), FALSE); - aud_playlist_set_active (new_list); -} - -static void -playlistwin_select_search(void) -{ - GtkWidget *searchdlg_win, *searchdlg_grid; - GtkWidget *searchdlg_hbox, *searchdlg_logo, *searchdlg_helptext; - GtkWidget *searchdlg_entry_title, *searchdlg_label_title; - GtkWidget *searchdlg_entry_album, *searchdlg_label_album; - GtkWidget *searchdlg_entry_file_name, *searchdlg_label_file_name; - GtkWidget *searchdlg_entry_performer, *searchdlg_label_performer; - GtkWidget *searchdlg_checkbt_clearprevsel; - GtkWidget *searchdlg_checkbt_newplaylist; - GtkWidget *searchdlg_checkbt_autoenqueue; - int result; - - /* create dialog */ - searchdlg_win = gtk_dialog_new_with_buttons( - _("Search entries in active playlist") , GTK_WINDOW(mainwin) , - (GtkDialogFlags) (GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT), - _("Cancel") , GTK_RESPONSE_REJECT , _("Search") , GTK_RESPONSE_ACCEPT , nullptr ); - - /* help text and logo */ - searchdlg_hbox = gtk_hbox_new (FALSE, 6); - searchdlg_logo = gtk_image_new_from_icon_name( "edit-find" , GTK_ICON_SIZE_DIALOG ); - searchdlg_helptext = gtk_label_new( _("Select entries in playlist by filling one or more " - "fields. Fields use regular expressions syntax, case-insensitive. If you don't know how " - "regular expressions work, simply insert a literal portion of what you're searching for.") ); - gtk_label_set_line_wrap( GTK_LABEL(searchdlg_helptext) , TRUE ); - gtk_box_pack_start( GTK_BOX(searchdlg_hbox) , searchdlg_logo , FALSE , FALSE , 0 ); - gtk_box_pack_start( GTK_BOX(searchdlg_hbox) , searchdlg_helptext , FALSE , FALSE , 0 ); - - /* title */ - searchdlg_label_title = gtk_label_new( _("Title:") ); - gtk_misc_set_alignment ((GtkMisc *) searchdlg_label_title, 1, 0.5); - searchdlg_entry_title = gtk_entry_new(); - g_signal_connect( searchdlg_entry_title , "key-press-event" , - G_CALLBACK(playlistwin_select_search_kp_cb) , searchdlg_win ); - - /* album */ - searchdlg_label_album= gtk_label_new( _("Album:") ); - gtk_misc_set_alignment ((GtkMisc *) searchdlg_label_album, 1, 0.5); - searchdlg_entry_album= gtk_entry_new(); - g_signal_connect( searchdlg_entry_album , "key-press-event" , - G_CALLBACK(playlistwin_select_search_kp_cb) , searchdlg_win ); - - /* artist */ - searchdlg_label_performer = gtk_label_new( _("Artist:") ); - gtk_misc_set_alignment ((GtkMisc *) searchdlg_label_performer, 1, 0.5); - searchdlg_entry_performer = gtk_entry_new(); - g_signal_connect( searchdlg_entry_performer , "key-press-event" , - G_CALLBACK(playlistwin_select_search_kp_cb) , searchdlg_win ); - - /* file name */ - searchdlg_label_file_name = gtk_label_new( _("File Name:") ); - gtk_misc_set_alignment ((GtkMisc *) searchdlg_label_file_name, 1, 0.5); - searchdlg_entry_file_name = gtk_entry_new(); - g_signal_connect( searchdlg_entry_file_name , "key-press-event" , - G_CALLBACK(playlistwin_select_search_kp_cb) , searchdlg_win ); - - /* some options that control behaviour */ - searchdlg_checkbt_clearprevsel = gtk_check_button_new_with_label( - _("Clear previous selection before searching") ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(searchdlg_checkbt_clearprevsel) , TRUE ); - searchdlg_checkbt_autoenqueue = gtk_check_button_new_with_label( - _("Automatically toggle queue for matching entries") ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(searchdlg_checkbt_autoenqueue) , FALSE ); - searchdlg_checkbt_newplaylist = gtk_check_button_new_with_label( - _("Create a new playlist with matching entries") ); - gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON(searchdlg_checkbt_newplaylist) , FALSE ); - g_signal_connect( searchdlg_checkbt_autoenqueue , "clicked" , - G_CALLBACK(playlistwin_select_search_cbt_cb) , searchdlg_checkbt_newplaylist ); - g_signal_connect( searchdlg_checkbt_newplaylist , "clicked" , - G_CALLBACK(playlistwin_select_search_cbt_cb) , searchdlg_checkbt_autoenqueue ); - - /* place fields in searchdlg_grid */ - searchdlg_grid = gtk_table_new (0, 0, FALSE); - gtk_table_set_row_spacings (GTK_TABLE (searchdlg_grid), 6); - gtk_table_set_col_spacings (GTK_TABLE (searchdlg_grid), 6); - gtk_table_attach_defaults (GTK_TABLE (searchdlg_grid), searchdlg_hbox, 0, 2, 0, 1); - gtk_table_attach (GTK_TABLE (searchdlg_grid), searchdlg_label_title, 0, 1, 1, 2, GTK_FILL, GTK_FILL, 0, 0); - gtk_table_attach_defaults (GTK_TABLE (searchdlg_grid), searchdlg_entry_title, 1, 2, 1, 2); - gtk_table_attach (GTK_TABLE (searchdlg_grid), searchdlg_label_album, 0, 1, 2, 3, GTK_FILL, GTK_FILL, 0, 0); - gtk_table_attach_defaults (GTK_TABLE (searchdlg_grid), searchdlg_entry_album, 1, 2, 2, 3); - gtk_table_attach (GTK_TABLE (searchdlg_grid), searchdlg_label_performer, 0, 1, 3, 4, GTK_FILL, GTK_FILL, 0, 0); - gtk_table_attach_defaults (GTK_TABLE (searchdlg_grid), searchdlg_entry_performer, 1, 2, 3, 4); - gtk_table_attach (GTK_TABLE (searchdlg_grid), searchdlg_label_file_name, 0, 1, 4, 5, GTK_FILL, GTK_FILL, 0, 0); - gtk_table_attach_defaults (GTK_TABLE (searchdlg_grid), searchdlg_entry_file_name, 1, 2, 4, 5); - gtk_table_attach_defaults (GTK_TABLE (searchdlg_grid), searchdlg_checkbt_clearprevsel, 0, 2, 5, 6); - gtk_table_attach_defaults (GTK_TABLE (searchdlg_grid), searchdlg_checkbt_autoenqueue, 0, 2, 6, 7); - gtk_table_attach_defaults (GTK_TABLE (searchdlg_grid), searchdlg_checkbt_newplaylist, 0, 2, 7, 8); - - gtk_container_set_border_width( GTK_CONTAINER(searchdlg_grid) , 5 ); - gtk_container_add ( GTK_CONTAINER(gtk_dialog_get_content_area - (GTK_DIALOG(searchdlg_win))) , searchdlg_grid ); - gtk_widget_show_all( searchdlg_win ); - result = gtk_dialog_run( GTK_DIALOG(searchdlg_win) ); - - switch(result) - { - case GTK_RESPONSE_ACCEPT: - { - /* create a TitleInput tuple with user search data */ - Tuple tuple; - char *searchdata = nullptr; - - searchdata = (char*)gtk_entry_get_text( GTK_ENTRY(searchdlg_entry_title) ); - AUDDBG("title=\"%s\"\n", searchdata); - tuple.set_str (Tuple::Title, searchdata); - - searchdata = (char*)gtk_entry_get_text( GTK_ENTRY(searchdlg_entry_album) ); - AUDDBG("album=\"%s\"\n", searchdata); - tuple.set_str (Tuple::Album, searchdata); - - searchdata = (char*)gtk_entry_get_text( GTK_ENTRY(searchdlg_entry_performer) ); - AUDDBG("performer=\"%s\"\n", searchdata); - tuple.set_str (Tuple::Artist, searchdata); - - searchdata = (char*)gtk_entry_get_text( GTK_ENTRY(searchdlg_entry_file_name) ); - AUDDBG("filename=\"%s\"\n", searchdata); - tuple.set_str (Tuple::Basename, searchdata); - - /* check if previous selection should be cleared before searching */ - if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(searchdlg_checkbt_clearprevsel)) == TRUE ) - playlistwin_select_none(); - - aud_playlist_select_by_patterns (active_playlist, tuple); - - /* check if a new playlist should be created after searching */ - if ( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(searchdlg_checkbt_newplaylist)) == TRUE ) - copy_selected_to_new (active_playlist); - else - { - /* set focus on the first entry found */ - int entries = aud_playlist_entry_count (active_playlist); - int count; - - for (count = 0; count < entries; count ++) - { - if (aud_playlist_entry_get_selected (active_playlist, count)) - { - ui_skinned_playlist_set_focused (playlistwin_list, count); - break; - } - } - - /* check if matched entries should be queued */ - if (gtk_toggle_button_get_active ((GtkToggleButton *) - searchdlg_checkbt_autoenqueue)) - aud_playlist_queue_insert_selected (active_playlist, -1); - } - - playlistwin_update (); - break; - } - default: - break; - } - /* done here :) */ - gtk_widget_destroy( searchdlg_win ); -} - -static void playlistwin_inverse_selection (void) -{ - int entries = aud_playlist_entry_count (active_playlist); - int entry; - - for (entry = 0; entry < entries; entry ++) - aud_playlist_entry_set_selected (active_playlist, entry, - ! aud_playlist_entry_get_selected (active_playlist, entry)); -} - -/* note: height is ignored if the window is shaded */ -static void playlistwin_resize (int w, int h) -{ - int tx, ty; - - g_return_if_fail(w > 0 && h > 0); - - tx = (w - PLAYLISTWIN_MIN_WIDTH) / PLAYLISTWIN_WIDTH_SNAP; - tx = (tx * PLAYLISTWIN_WIDTH_SNAP) + PLAYLISTWIN_MIN_WIDTH; - if (tx < PLAYLISTWIN_MIN_WIDTH) - tx = PLAYLISTWIN_MIN_WIDTH; - - if (! aud_get_bool ("skins", "playlist_shaded")) - { - ty = (h - PLAYLISTWIN_MIN_HEIGHT) / PLAYLISTWIN_HEIGHT_SNAP; - ty = (ty * PLAYLISTWIN_HEIGHT_SNAP) + PLAYLISTWIN_MIN_HEIGHT; - if (ty < PLAYLISTWIN_MIN_HEIGHT) - ty = PLAYLISTWIN_MIN_HEIGHT; - } - else - ty = config.playlist_height; - - if (tx == config.playlist_width && ty == config.playlist_height) - return; - - config.playlist_width = w = tx; - config.playlist_height = h = ty; - - ui_skinned_playlist_resize (playlistwin_list, w - 31, h - 58); - window_move_widget (playlistwin, FALSE, playlistwin_slider, w - 15, 20); - ui_skinned_playlist_slider_resize (playlistwin_slider, h - 58); - - window_move_widget (playlistwin, TRUE, playlistwin_shaded_shade, w - 21, 3); - window_move_widget (playlistwin, TRUE, playlistwin_shaded_close, w - 11, 3); - window_move_widget (playlistwin, FALSE, playlistwin_shade, w - 21, 3); - window_move_widget (playlistwin, FALSE, playlistwin_close, w - 11, 3); - - window_move_widget (playlistwin, FALSE, playlistwin_time_min, w - 82, h - 15); - window_move_widget (playlistwin, FALSE, playlistwin_time_sec, w - 64, h - 15); - window_move_widget (playlistwin, FALSE, playlistwin_info, w - 143, h - 28); - - window_move_widget (playlistwin, FALSE, playlistwin_srew, w - 144, h - 16); - window_move_widget (playlistwin, FALSE, playlistwin_splay, w - 138, h - 16); - window_move_widget (playlistwin, FALSE, playlistwin_spause, w - 128, h - 16); - window_move_widget (playlistwin, FALSE, playlistwin_sstop, w - 118, h - 16); - window_move_widget (playlistwin, FALSE, playlistwin_sfwd, w - 109, h - 16); - window_move_widget (playlistwin, FALSE, playlistwin_seject, w - 100, h - 16); - window_move_widget (playlistwin, FALSE, playlistwin_sscroll_up, w - 14, h - 35); - window_move_widget (playlistwin, FALSE, playlistwin_sscroll_down, w - 14, h - 30); - - window_move_widget (playlistwin, FALSE, resize_handle, w - 20, h - 20); - window_move_widget (playlistwin, TRUE, sresize_handle, w - 31, 0); - - textbox_set_width (playlistwin_sinfo, w - 35); - - window_move_widget (playlistwin, FALSE, button_add, 12, h - 29); - window_move_widget (playlistwin, FALSE, button_sub, 40, h - 29); - window_move_widget (playlistwin, FALSE, button_sel, 68, h - 29); - window_move_widget (playlistwin, FALSE, button_misc, 100, h - 29); - window_move_widget (playlistwin, FALSE, button_list, w - 46, h - 29); -} - -static void -playlistwin_fileinfo(void) -{ - audgui_infowin_show (active_playlist, aud_playlist_get_focus (active_playlist)); -} - -static void -playlistwin_scrolled(GtkWidget * widget, - GdkEventScroll * event, - void * callback_data) -{ - switch (event->direction) - { - case GDK_SCROLL_DOWN: - playlistwin_scroll (FALSE); - break; - case GDK_SCROLL_UP: - playlistwin_scroll (TRUE); - break; - default: - break; - } -} - -static gboolean -playlistwin_press(GtkWidget * widget, - GdkEventButton * event, - void * callback_data) -{ - if (event->button == 1 && event->type == GDK_2BUTTON_PRESS && - event->window == gtk_widget_get_window (widget) && event->y < 14) - playlistwin_shade_toggle(); - else if (event->button == 3) - menu_popup (UI_MENU_PLAYLIST, event->x_root, event->y_root, FALSE, FALSE, 3, event->time); - - return TRUE; -} - -void -playlistwin_hide_timer(void) -{ - textbox_set_text (playlistwin_time_min, " "); - textbox_set_text (playlistwin_time_sec, " "); -} - -void playlistwin_set_time (const char * minutes, const char * seconds) -{ - textbox_set_text (playlistwin_time_min, minutes); - textbox_set_text (playlistwin_time_sec, seconds); -} - -static void drag_motion (GtkWidget * widget, GdkDragContext * context, int x, - int y, unsigned time, void * unused) -{ - if (! aud_get_bool ("skins", "playlist_shaded")) - ui_skinned_playlist_hover (playlistwin_list, x - 12, y - 20); -} - -static void drag_leave (GtkWidget * widget, GdkDragContext * context, unsigned time, - void * unused) -{ - if (! aud_get_bool ("skins", "playlist_shaded")) - ui_skinned_playlist_hover_end (playlistwin_list); -} - -static void drag_drop (GtkWidget * widget, GdkDragContext * context, int x, - int y, unsigned time, void * unused) -{ - if (aud_get_bool ("skins", "playlist_shaded")) - drop_position = -1; - else - { - ui_skinned_playlist_hover (playlistwin_list, x - 12, y - 20); - drop_position = ui_skinned_playlist_hover_end (playlistwin_list); - } -} - -static void drag_data_received (GtkWidget * widget, GdkDragContext * context, - int x, int y, GtkSelectionData * data, unsigned info, unsigned time, void * unused) -{ - audgui_urilist_insert (active_playlist, drop_position, (const char *) - gtk_selection_data_get_data (data)); - drop_position = -1; -} - -static void playlistwin_hide (void) -{ - view_set_show_playlist (FALSE); -} - -static void resize_press (void) -{ - resize_base_width = config.playlist_width; - resize_base_height = config.playlist_height; -} - -static void resize_drag (int x_offset, int y_offset) -{ - gboolean shaded = aud_get_bool ("skins", "playlist_shaded"); - - /* compromise between rounding and truncating; this has no real - * justification at all other than it "looks about right". */ - playlistwin_resize (resize_base_width + x_offset + PLAYLISTWIN_WIDTH_SNAP / - 3, resize_base_height + y_offset + PLAYLISTWIN_HEIGHT_SNAP / 3); - window_set_size (playlistwin, config.playlist_width, shaded ? - PLAYLISTWIN_SHADED_HEIGHT : config.playlist_height); -} - -static void button_add_cb (GtkWidget * button, GdkEventButton * event) -{ - int xpos, ypos; - gtk_window_get_position ((GtkWindow *) playlistwin, & xpos, & ypos); - menu_popup (UI_MENU_PLAYLIST_ADD, xpos + 12 * config.scale, - ypos + (config.playlist_height - 8) * config.scale, FALSE, TRUE, - event->button, event->time); -} - -static void button_sub_cb (GtkWidget * button, GdkEventButton * event) -{ - int xpos, ypos; - gtk_window_get_position ((GtkWindow *) playlistwin, & xpos, & ypos); - menu_popup (UI_MENU_PLAYLIST_REMOVE, xpos + 40 * config.scale, - ypos + (config.playlist_height - 8) * config.scale, FALSE, TRUE, - event->button, event->time); -} - -static void button_sel_cb (GtkWidget * button, GdkEventButton * event) -{ - int xpos, ypos; - gtk_window_get_position ((GtkWindow *) playlistwin, & xpos, & ypos); - menu_popup (UI_MENU_PLAYLIST_SELECT, xpos + 68 * config.scale, - ypos + (config.playlist_height - 8) * config.scale, FALSE, TRUE, - event->button, event->time); -} - -static void button_misc_cb (GtkWidget * button, GdkEventButton * event) -{ - int xpos, ypos; - gtk_window_get_position ((GtkWindow *) playlistwin, & xpos, & ypos); - menu_popup (UI_MENU_PLAYLIST_SORT, xpos + 100 * config.scale, - ypos + (config.playlist_height - 8) * config.scale, FALSE, TRUE, - event->button, event->time); -} - -static void button_list_cb (GtkWidget * button, GdkEventButton * event) -{ - int xpos, ypos; - gtk_window_get_position ((GtkWindow *) playlistwin, & xpos, & ypos); - menu_popup (UI_MENU_PLAYLIST, - xpos + (config.playlist_width - 12) * config.scale, - ypos + (config.playlist_height - 8) * config.scale, TRUE, TRUE, - event->button, event->time); -} - -static void -playlistwin_create_widgets(void) -{ - int w = config.playlist_width, h = config.playlist_height; - - playlistwin_sinfo = textbox_new (w - 35, "", nullptr, config.autoscroll); - window_put_widget (playlistwin, TRUE, playlistwin_sinfo, 4, 4); - - playlistwin_shaded_shade = button_new (9, 9, 128, 45, 150, 42, SKIN_PLEDIT, SKIN_PLEDIT); - window_put_widget (playlistwin, TRUE, playlistwin_shaded_shade, w - 21, 3); - button_on_release (playlistwin_shaded_shade, (ButtonCB) playlistwin_shade_toggle); - - playlistwin_shaded_close = button_new (9, 9, 138, 45, 52, 42, SKIN_PLEDIT, SKIN_PLEDIT); - window_put_widget (playlistwin, TRUE, playlistwin_shaded_close, w - 11, 3); - button_on_release (playlistwin_shaded_close, (ButtonCB) playlistwin_hide); - - playlistwin_shade = button_new (9, 9, 157, 3, 62, 42, SKIN_PLEDIT, SKIN_PLEDIT); - window_put_widget (playlistwin, FALSE, playlistwin_shade, w - 21, 3); - button_on_release (playlistwin_shade, (ButtonCB) playlistwin_shade_toggle); - - playlistwin_close = button_new (9, 9, 167, 3, 52, 42, SKIN_PLEDIT, SKIN_PLEDIT); - window_put_widget (playlistwin, FALSE, playlistwin_close, w - 11, 3); - button_on_release (playlistwin_close, (ButtonCB) playlistwin_hide); - - String font = aud_get_str ("skins", "playlist_font"); - playlistwin_list = ui_skinned_playlist_new (w - 31, h - 58, font); - window_put_widget (playlistwin, FALSE, playlistwin_list, 12, 20); - - /* playlist list box slider */ - playlistwin_slider = ui_skinned_playlist_slider_new (playlistwin_list, h - 58); - window_put_widget (playlistwin, FALSE, playlistwin_slider, w - 15, 20); - ui_skinned_playlist_set_slider (playlistwin_list, playlistwin_slider); - - playlistwin_time_min = textbox_new (15, "", nullptr, FALSE); - window_put_widget (playlistwin, FALSE, playlistwin_time_min, w - 82, h - 15); - - playlistwin_time_sec = textbox_new (10, "", nullptr, FALSE); - window_put_widget (playlistwin, FALSE, playlistwin_time_sec, w - 64, h - 15); - - g_signal_connect(playlistwin_time_min, "button-press-event", G_CALLBACK(change_timer_mode_cb), nullptr); - g_signal_connect(playlistwin_time_sec, "button-press-event", G_CALLBACK(change_timer_mode_cb), nullptr); - - playlistwin_info = textbox_new (90, "", nullptr, FALSE); - window_put_widget (playlistwin, FALSE, playlistwin_info, w - 143, h - 28); - - /* mini play control buttons at right bottom corner */ - - playlistwin_srew = button_new_small (8, 7); - window_put_widget (playlistwin, FALSE, playlistwin_srew, w - 144, h - 16); - button_on_release (playlistwin_srew, (ButtonCB) aud_drct_pl_prev); - - playlistwin_splay = button_new_small (10, 7); - window_put_widget (playlistwin, FALSE, playlistwin_splay, w - 138, h - 16); - button_on_release (playlistwin_splay, (ButtonCB) aud_drct_play); - - playlistwin_spause = button_new_small (10, 7); - window_put_widget (playlistwin, FALSE, playlistwin_spause, w - 128, h - 16); - button_on_release (playlistwin_spause, (ButtonCB) aud_drct_pause); - - playlistwin_sstop = button_new_small (9, 7); - window_put_widget (playlistwin, FALSE, playlistwin_sstop, w - 118, h - 16); - button_on_release (playlistwin_sstop, (ButtonCB) aud_drct_stop); - - playlistwin_sfwd = button_new_small (8, 7); - window_put_widget (playlistwin, FALSE, playlistwin_sfwd, w - 109, h - 16); - button_on_release (playlistwin_sfwd, (ButtonCB) aud_drct_pl_next); - - playlistwin_seject = button_new_small (9, 7); - window_put_widget (playlistwin, FALSE, playlistwin_seject, w - 100, h - 16); - button_on_release (playlistwin_seject, (ButtonCB) action_play_file); - - playlistwin_sscroll_up = button_new_small (8, 5); - window_put_widget (playlistwin, FALSE, playlistwin_sscroll_up, w - 14, h - 35); - button_on_release (playlistwin_sscroll_up, (ButtonCB) playlistwin_scroll_up_pushed); - - playlistwin_sscroll_down = button_new_small (8, 5); - window_put_widget (playlistwin, FALSE, playlistwin_sscroll_down, w - 14, h - 30); - button_on_release (playlistwin_sscroll_down, (ButtonCB) playlistwin_scroll_down_pushed); - - /* resize handles */ - - resize_handle = drag_handle_new (20, 20, resize_press, resize_drag); - window_put_widget (playlistwin, FALSE, resize_handle, w - 20, h - 20); - - sresize_handle = drag_handle_new (9, PLAYLISTWIN_SHADED_HEIGHT, resize_press, resize_drag); - window_put_widget (playlistwin, TRUE, sresize_handle, w - 31, 0); - - /* lower button row */ - - button_add = button_new_small (25, 18); - window_put_widget (playlistwin, FALSE, button_add, 12, h - 29); - button_on_press (button_add, button_add_cb); - - button_sub = button_new_small (25, 18); - window_put_widget (playlistwin, FALSE, button_sub, 40, h - 29); - button_on_press (button_sub, button_sub_cb); - - button_sel = button_new_small (25, 18); - window_put_widget (playlistwin, FALSE, button_sel, 68, h - 29); - button_on_press (button_sel, button_sel_cb); - - button_misc = button_new_small (25, 18); - window_put_widget (playlistwin, FALSE, button_misc, 100, h - 29); - button_on_press (button_misc, button_misc_cb); - - button_list = button_new_small (23, 18); - window_put_widget (playlistwin, FALSE, button_list, w - 46, h - 29); - button_on_press (button_list, button_list_cb); -} - -static void pl_win_draw (GtkWidget * window, cairo_t * cr) -{ - if (aud_get_bool ("skins", "playlist_shaded")) - skin_draw_playlistwin_shaded (cr, config.playlist_width, TRUE); - else - skin_draw_playlistwin_frame (cr, config.playlist_width, - config.playlist_height, TRUE); -} - -static void -playlistwin_create_window(void) -{ - gboolean shaded = aud_get_bool ("skins", "playlist_shaded"); - - playlistwin = window_new (& config.playlist_x, & config.playlist_y, - config.playlist_width, shaded ? PLAYLISTWIN_SHADED_HEIGHT : - config.playlist_height, FALSE, shaded, pl_win_draw); - - gtk_window_set_title(GTK_WINDOW(playlistwin), _("Audacious Playlist Editor")); - - gtk_window_set_transient_for(GTK_WINDOW(playlistwin), - GTK_WINDOW(mainwin)); - gtk_window_set_skip_pager_hint(GTK_WINDOW(playlistwin), TRUE); - gtk_window_set_skip_taskbar_hint(GTK_WINDOW(playlistwin), TRUE); - - gtk_widget_add_events(playlistwin, GDK_POINTER_MOTION_MASK | - GDK_FOCUS_CHANGE_MASK | GDK_BUTTON_MOTION_MASK | - GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | - GDK_SCROLL_MASK | GDK_VISIBILITY_NOTIFY_MASK); - - g_signal_connect (playlistwin, "delete-event", (GCallback) handle_window_close, nullptr); - g_signal_connect (playlistwin, "button-press-event", (GCallback) playlistwin_press, nullptr); - g_signal_connect (playlistwin, "scroll-event", (GCallback) playlistwin_scrolled, nullptr); - g_signal_connect (playlistwin, "key-press-event", (GCallback) mainwin_keypress, nullptr); - - drag_dest_set (playlistwin); - drop_position = -1; - - g_signal_connect (playlistwin, "drag-motion", (GCallback) drag_motion, nullptr); - g_signal_connect (playlistwin, "drag-leave", (GCallback) drag_leave, nullptr); - g_signal_connect (playlistwin, "drag-drop", (GCallback) drag_drop, nullptr); - g_signal_connect (playlistwin, "drag-data-received", (GCallback) drag_data_received, nullptr); -} - -static void get_title (void) -{ - int playlists = aud_playlist_count (); - - g_free (active_title); - - if (playlists > 1) - { - String title = aud_playlist_get_title (active_playlist); - active_title = g_strdup_printf (_("%s (%d of %d)"), - (const char *) title, 1 + active_playlist, playlists); - } - else - active_title = nullptr; -} - -static void update_cb (void * unused, void * another) -{ - int old = active_playlist; - - active_playlist = aud_playlist_get_active (); - active_length = aud_playlist_entry_count (active_playlist); - get_title (); - - if (active_playlist != old) - { - ui_skinned_playlist_scroll_to (playlistwin_list, 0); - song_changed = TRUE; - } - - if (song_changed) - { - ui_skinned_playlist_set_focused (playlistwin_list, - aud_playlist_get_position (active_playlist)); - song_changed = FALSE; - } - - real_update (); -} - -static void follow_cb (void * data, void * another) -{ - int list = aud::from_ptr<int> (data); - aud_playlist_select_all (list, FALSE); - - int row = aud_playlist_get_position (list); - if (row >= 0) - aud_playlist_entry_set_selected (list, row, TRUE); - - if (list == active_playlist) - song_changed = TRUE; -} - -void -playlistwin_create(void) -{ - active_playlist = aud_playlist_get_active (); - active_length = aud_playlist_entry_count (active_playlist); - active_title = nullptr; - get_title (); - - playlistwin_create_window(); - - playlistwin_create_widgets(); - window_show_all (playlistwin); - - gtk_window_add_accel_group ((GtkWindow *) playlistwin, menu_get_accel_group ()); - - aud_playlist_select_all (active_playlist, FALSE); - - int row = aud_playlist_get_position (active_playlist); - if (row >= 0) - aud_playlist_entry_set_selected (active_playlist, row, TRUE); - - ui_skinned_playlist_set_focused (playlistwin_list, row); - - song_changed = FALSE; - - hook_associate ("playlist position", follow_cb, nullptr); - hook_associate ("playlist activate", update_cb, nullptr); - hook_associate ("playlist update", update_cb, nullptr); -} - -void playlistwin_unhook (void) -{ - hook_dissociate ("playlist position", follow_cb); - hook_dissociate ("playlist activate", update_cb); - hook_dissociate ("playlist update", update_cb); - g_free (active_title); - active_title = nullptr; -} - -void action_playlist_track_info(void) -{ - playlistwin_fileinfo(); -} - -void action_queue_toggle (void) -{ - int focus = aud_playlist_get_focus (active_playlist); - if (focus == -1) - return; - - /* make sure focused row is selected */ - if (! aud_playlist_entry_get_selected (active_playlist, focus)) - { - aud_playlist_select_all (active_playlist, false); - aud_playlist_entry_set_selected (active_playlist, focus, true); - } - - int at = aud_playlist_queue_find_entry (active_playlist, focus); - - if (at == -1) - aud_playlist_queue_insert_selected (active_playlist, -1); - else - aud_playlist_queue_delete_selected (active_playlist); -} - -void action_playlist_sort_by_track_number (void) -{ - aud_playlist_sort_by_scheme (active_playlist, Playlist::Track); -} - -void action_playlist_sort_by_title (void) -{ - aud_playlist_sort_by_scheme (active_playlist, Playlist::Title); -} - -void action_playlist_sort_by_album (void) -{ - aud_playlist_sort_by_scheme (active_playlist, Playlist::Album); -} - -void action_playlist_sort_by_artist (void) -{ - aud_playlist_sort_by_scheme (active_playlist, Playlist::Artist); -} - -void action_playlist_sort_by_album_artist (void) -{ - aud_playlist_sort_by_scheme (active_playlist, Playlist::AlbumArtist); -} - -void action_playlist_sort_by_full_path (void) -{ - aud_playlist_sort_by_scheme (active_playlist, Playlist::Path); -} - -void action_playlist_sort_by_date (void) -{ - aud_playlist_sort_by_scheme (active_playlist, Playlist::Date); -} - -void action_playlist_sort_by_length (void) -{ - aud_playlist_sort_by_scheme (active_playlist, Playlist::Length); -} - -void action_playlist_sort_by_genre (void) -{ - aud_playlist_sort_by_scheme (active_playlist, Playlist::Genre); -} - -void action_playlist_sort_by_filename (void) -{ - aud_playlist_sort_by_scheme (active_playlist, Playlist::Filename); -} - -void action_playlist_sort_by_custom_title (void) -{ - aud_playlist_sort_by_scheme (active_playlist, Playlist::FormattedTitle); -} - -void action_playlist_sort_selected_by_track_number (void) -{ - aud_playlist_sort_selected_by_scheme (active_playlist, Playlist::Track); -} - -void action_playlist_sort_selected_by_title (void) -{ - aud_playlist_sort_selected_by_scheme (active_playlist, Playlist::Title); -} - -void action_playlist_sort_selected_by_album (void) -{ - aud_playlist_sort_selected_by_scheme (active_playlist, Playlist::Album); -} - -void action_playlist_sort_selected_by_artist (void) -{ - aud_playlist_sort_selected_by_scheme (active_playlist, Playlist::Artist); -} - -void action_playlist_sort_selected_by_album_artist (void) -{ - aud_playlist_sort_selected_by_scheme (active_playlist, Playlist::AlbumArtist); -} - -void action_playlist_sort_selected_by_length (void) -{ - aud_playlist_sort_selected_by_scheme (active_playlist, Playlist::Length); -} - -void action_playlist_sort_selected_by_genre (void) -{ - aud_playlist_sort_selected_by_scheme (active_playlist, Playlist::Genre); -} - -void action_playlist_sort_selected_by_full_path (void) -{ - aud_playlist_sort_selected_by_scheme (active_playlist, Playlist::Path); -} - -void action_playlist_sort_selected_by_date (void) -{ - aud_playlist_sort_selected_by_scheme (active_playlist, Playlist::Date); -} - -void action_playlist_sort_selected_by_filename (void) -{ - aud_playlist_sort_selected_by_scheme (active_playlist, Playlist::Filename); -} - -void action_playlist_sort_selected_by_custom_title (void) -{ - aud_playlist_sort_selected_by_scheme (active_playlist, Playlist::FormattedTitle); -} - -void action_playlist_randomize_list (void) -{ - aud_playlist_randomize (active_playlist); -} - -void action_playlist_reverse_list (void) -{ - aud_playlist_reverse (active_playlist); -} - -void action_playlist_clear_queue (void) -{ - aud_playlist_queue_delete (active_playlist, 0, aud_playlist_queue_count - (active_playlist)); -} - -void action_playlist_remove_unavailable (void) -{ - aud_playlist_remove_failed (active_playlist); -} - -void action_playlist_remove_dupes_by_title (void) -{ - aud_playlist_remove_duplicates_by_scheme (active_playlist, Playlist::Title); -} - -void action_playlist_remove_dupes_by_filename (void) -{ - aud_playlist_remove_duplicates_by_scheme (active_playlist, Playlist::Filename); -} - -void action_playlist_remove_dupes_by_full_path (void) -{ - aud_playlist_remove_duplicates_by_scheme (active_playlist, Playlist::Path); -} - -void action_playlist_remove_all (void) -{ - aud_playlist_entry_delete (active_playlist, 0, aud_playlist_entry_count - (active_playlist)); -} - -void action_playlist_remove_selected (void) -{ - aud_playlist_delete_selected (active_playlist); -} - -void action_playlist_remove_unselected (void) -{ - playlistwin_inverse_selection (); - aud_playlist_delete_selected (active_playlist); - aud_playlist_select_all (active_playlist, TRUE); -} - -void action_playlist_copy (void) -{ - GtkClipboard * clip = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); - Index<char> list = audgui_urilist_create_from_selected (active_playlist); - - if (! list.len ()) - return; - - gtk_clipboard_set_text (clip, list.begin (), list.len ()); -} - -void action_playlist_cut (void) -{ - action_playlist_copy (); - action_playlist_remove_selected (); -} - -void action_playlist_paste (void) -{ - GtkClipboard * clip = gtk_clipboard_get (GDK_SELECTION_CLIPBOARD); - char * list = gtk_clipboard_wait_for_text (clip); - - if (list == nullptr) - return; - - audgui_urilist_insert (active_playlist, - aud_playlist_get_focus (active_playlist), list); - g_free (list); -} - -void -action_playlist_add_files(void) -{ - audgui_run_filebrowser(FALSE); /* FALSE = NO_PLAY_BUTTON */ -} - -void -action_playlist_add_url(void) -{ - audgui_show_add_url_window (FALSE); -} - -void action_playlist_play (void) -{ - aud_playlist_play (aud_playlist_get_active ()); -} - -void action_playlist_new (void) -{ - int playlist = aud_playlist_count (); - - aud_playlist_insert (playlist); - aud_playlist_set_active (playlist); -} - -void action_playlist_prev (void) -{ - if (active_playlist > 0) - aud_playlist_set_active (active_playlist - 1); - else - { - int count = aud_playlist_count (); - if (count > 1) - aud_playlist_set_active (count - 1); - } -} - -void action_playlist_next (void) -{ - int count = aud_playlist_count (); - - if (active_playlist + 1 < count) - aud_playlist_set_active (active_playlist + 1); - else if (count > 1) - aud_playlist_set_active (0); -} - -void action_playlist_rename (void) -{ - audgui_show_playlist_rename (active_playlist); -} - -void action_playlist_delete (void) -{ - audgui_confirm_playlist_delete (active_playlist); -} - -void -action_playlist_refresh_list(void) -{ - aud_playlist_rescan (active_playlist); -} - -void -action_playlist_search_and_select(void) -{ - playlistwin_select_search(); -} - -void -action_playlist_invert_selection(void) -{ - playlistwin_inverse_selection(); -} - -void -action_playlist_select_none(void) -{ - playlistwin_select_none(); -} - -void -action_playlist_select_all(void) -{ - playlistwin_select_all(); -} - - -static void -playlistwin_select_search_cbt_cb(GtkWidget *called_cbt, void * other_cbt) -{ - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(called_cbt)) == TRUE) - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(other_cbt), FALSE); - return; -} - -static gboolean -playlistwin_select_search_kp_cb(GtkWidget *entry, GdkEventKey *event, - void * searchdlg_win) -{ - switch (event->keyval) - { - case GDK_KEY_Return: - gtk_dialog_response(GTK_DIALOG(searchdlg_win), GTK_RESPONSE_ACCEPT); - return TRUE; - default: - return FALSE; - } -} diff --git a/src/skins/ui_skin.cc b/src/skins/ui_skin.cc deleted file mode 100644 index d858114..0000000 --- a/src/skins/ui_skin.cc +++ /dev/null @@ -1,809 +0,0 @@ -/* Audacious - * Copyright (C) 2005-2011 Audacious development team. - * - * BMP - Cross-platform multimedia player - * Copyright (C) 2003-2004 BMP development team. - * - * Based on XMMS: - * Copyright (C) 1998-2003 XMMS development team. - * - * 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; under version 3 of the License. - * - * 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 <http://www.gnu.org/licenses>. - * - * The Audacious team does not consider modular code linking to - * Audacious or using our public API to be a derived work. - */ - -#include <errno.h> -#include <stdlib.h> -#include <string.h> -#include <sys/stat.h> - -#include <gtk/gtk.h> - -#include <libaudcore/runtime.h> -#include <libaudcore/runtime.h> - -#include "plugin.h" -#include "skins_cfg.h" -#include "surface.h" -#include "ui_equalizer.h" -#include "ui_main.h" -#include "ui_playlist.h" -#include "ui_skin.h" -#include "ui_skinned_number.h" -#include "ui_skinned_playstatus.h" -#include "ui_skinned_textbox.h" -#include "ui_skinned_window.h" -#include "ui_skinselector.h" -#include "ui_vis.h" -#include "util.h" - -#define EXTENSION_TARGETS 7 - -static const char *ext_targets[EXTENSION_TARGETS] = -{ "bmp", "xpm", "png", "svg", "gif", "jpg", "jpeg" }; - -struct _SkinPixmapIdMapping { - SkinPixmapId id; - const char *name; - const char *alt_name; - int width, height; -}; - -typedef struct _SkinPixmapIdMapping SkinPixmapIdMapping; - -static gboolean skin_load (Skin * skin, const char * path); - -Skin *active_skin = nullptr; - -static SkinPixmapIdMapping skin_pixmap_id_map[] = { - {SKIN_MAIN, "main", nullptr, 0, 0}, - {SKIN_CBUTTONS, "cbuttons", nullptr, 0, 0}, - {SKIN_SHUFREP, "shufrep", nullptr, 0, 0}, - {SKIN_TEXT, "text", nullptr, 0, 0}, - {SKIN_TITLEBAR, "titlebar", nullptr, 0, 0}, - {SKIN_VOLUME, "volume", nullptr, 0, 0}, - {SKIN_BALANCE, "balance", "volume", 0, 0}, - {SKIN_MONOSTEREO, "monoster", nullptr, 0, 0}, - {SKIN_PLAYPAUSE, "playpaus", nullptr, 0, 0}, - {SKIN_NUMBERS, "nums_ex", "numbers", 0, 0}, - {SKIN_POSBAR, "posbar", nullptr, 0, 0}, - {SKIN_EQMAIN, "eqmain", nullptr, 0, 0}, - {SKIN_PLEDIT, "pledit", nullptr, 0, 0}, - {SKIN_EQ_EX, "eq_ex", nullptr, 0, 0} -}; - -static const uint32_t default_vis_colors[24] = { - COLOR (9, 34, 53), - COLOR (10, 18, 26), - COLOR (0, 54, 108), - COLOR (0, 58, 116), - COLOR (0, 62, 124), - COLOR (0, 66, 132), - COLOR (0, 70, 140), - COLOR (0, 74, 148), - COLOR (0, 78, 156), - COLOR (0, 82, 164), - COLOR (0, 86, 172), - COLOR (0, 92, 184), - COLOR (0, 98, 196), - COLOR (0, 104, 208), - COLOR (0, 110, 220), - COLOR (0, 116, 232), - COLOR (0, 122, 244), - COLOR (0, 128, 255), - COLOR (0, 128, 255), - COLOR (0, 104, 208), - COLOR (0, 80, 160), - COLOR (0, 56, 112), - COLOR (0, 32, 64), - COLOR (200, 200, 200) -}; - -gboolean active_skin_load (const char * path) -{ - AUDDBG("%s\n", path); - g_return_val_if_fail(active_skin != nullptr, FALSE); - - if (!skin_load(active_skin, path)) { - AUDDBG("loading failed\n"); - return FALSE; - } - - mainwin_refresh_hints (); - textbox_update_all (); - ui_vis_set_colors (); - gtk_widget_queue_draw (mainwin); - gtk_widget_queue_draw (equalizerwin); - gtk_widget_queue_draw (playlistwin); - - aud_set_str ("skins", "skin", path); - - return TRUE; -} - -static Skin * -skin_new(void) -{ - Skin *skin; - skin = g_new0(Skin, 1); - return skin; -} - -/** - * Frees the data associated for skin. - * - * Does not free skin itself or lock variable so that the skin can immediately - * populated with new skin data if needed. - */ -static void -skin_free(Skin * skin) -{ - int i; - - g_return_if_fail(skin != nullptr); - - for (i = 0; i < SKIN_PIXMAP_COUNT; i++) - { - if (skin->pixmaps[i]) - { - cairo_surface_destroy (skin->pixmaps[i]); - skin->pixmaps[i] = nullptr; - } - } - - g_free(skin->path); - skin->path = nullptr; -} - -static void -skin_destroy(Skin * skin) -{ - g_return_if_fail(skin != nullptr); - skin_free(skin); - g_free(skin); -} - -static const SkinPixmapIdMapping * -skin_pixmap_id_lookup(unsigned id) -{ - for (auto & info : skin_pixmap_id_map) - { - if (info.id == id) - return & info; - } - - return nullptr; -} - -static char * skin_pixmap_locate (const char * dirname, char * * basenames) -{ - char * filename = nullptr; - int i; - - for (i = 0; basenames[i] != nullptr; i ++) - { - if ((filename = find_file_case_path (dirname, basenames[i])) != nullptr) - break; - } - - return filename; -} - -/** - * Creates possible file names for a pixmap. - * - * Basically this makes list of all possible file names that pixmap data - * can be found from by using the static ext_targets variable to get all - * possible extensions that pixmap file might have. - */ -static char ** -skin_pixmap_create_basenames(const SkinPixmapIdMapping * pixmap_id_mapping) -{ - char **basenames = g_new0 (char *, EXTENSION_TARGETS * 2 + 1); - int i, y; - - // Create list of all possible image formats that can be loaded - for (i = 0, y = 0; i < EXTENSION_TARGETS; i++, y++) - { - basenames[y] = - g_strdup_printf("%s.%s", pixmap_id_mapping->name, ext_targets[i]); - - if (pixmap_id_mapping->alt_name) - basenames[++y] = - g_strdup_printf("%s.%s", pixmap_id_mapping->alt_name, - ext_targets[i]); - } - - return basenames; -} - -/** - * Frees the data allocated by skin_pixmap_create_basenames - */ -static void -skin_pixmap_free_basenames(char ** basenames) -{ - int i; - for (i = 0; basenames[i] != nullptr; i++) - { - g_free(basenames[i]); - basenames[i] = nullptr; - } - g_free(basenames); -} - -/** - * Locates a pixmap file for skin. - */ -static char * -skin_pixmap_locate_basenames(const Skin * skin, - const SkinPixmapIdMapping * pixmap_id_mapping, - const char * path_p) -{ - char *filename = nullptr; - const char *path = path_p ? path_p : skin->path; - char **basenames = skin_pixmap_create_basenames(pixmap_id_mapping); - - filename = skin_pixmap_locate(path, basenames); - - skin_pixmap_free_basenames(basenames); - - if (! filename) - AUDERR ("Skin does not contain a \"%s\" pixmap.\n", - pixmap_id_mapping->name); - - return filename; -} - - -static gboolean -skin_load_pixmap_id(Skin * skin, SkinPixmapId id, const char * path_p) -{ - const SkinPixmapIdMapping *pixmap_id_mapping; - char *filename; - - g_return_val_if_fail(skin != nullptr, FALSE); - g_return_val_if_fail(id < SKIN_PIXMAP_COUNT, FALSE); - g_return_val_if_fail(! skin->pixmaps[id], FALSE); - - pixmap_id_mapping = skin_pixmap_id_lookup(id); - g_return_val_if_fail(pixmap_id_mapping != nullptr, FALSE); - - filename = skin_pixmap_locate_basenames(skin, pixmap_id_mapping, path_p); - - if (filename == nullptr) - return FALSE; - - skin->pixmaps[id] = surface_new_from_file (filename); - - g_free (filename); - return skin->pixmaps[id] ? TRUE : FALSE; -} - -static int color_diff (uint32_t a, uint32_t b) -{ - return abs (COLOR_R (a) - COLOR_R (b)) + abs (COLOR_G (a) - COLOR_G (b)) + - abs (COLOR_B (a) - COLOR_B (b)); -} - -static void skin_get_textcolors (Skin * skin, cairo_surface_t * s) -{ - /* - * Try to extract reasonable background and foreground colors - * from the font pixmap - */ - - /* Get a pixel from the middle of the space character */ - skin->colors[SKIN_TEXTBG] = surface_get_pixel (s, 152, 3); - - int max_d = -1; - for (int y = 0; y < 6; y ++) - { - for (int x = 1; x < 150; x ++) - { - int c = surface_get_pixel (s, x, y); - int d = color_diff (skin->colors[SKIN_TEXTBG], c); - if (d > max_d) - { - skin->colors[SKIN_TEXTFG] = c; - max_d = d; - } - } - } -} - -gboolean -init_skins(const char * path) -{ - active_skin = skin_new(); - - active_skin->properties = skin_default_hints; - - /* create the windows if they haven't been created yet, needed for bootstrapping */ - if (mainwin == nullptr) - { - mainwin_create(); - equalizerwin_create(); - playlistwin_create(); - } - - if (! path || ! active_skin_load (path)) - { - if (path != nullptr) - AUDDBG("Unable to load skin (%s), trying default...\n", path); - else - AUDDBG("Skin not defined: trying default...\n"); - - /* can't load configured skin, retry with default */ - char * def = g_strdup_printf ("%s" G_DIR_SEPARATOR_S "Skins" - G_DIR_SEPARATOR_S "Default", aud_get_path (AudPath::DataDir)); - - if (! active_skin_load (def)) - { - AUDDBG ("Unable to load default skin (%s)! Giving up.\n", def); - g_free (def); - return FALSE; - } - - g_free (def); - } - - return TRUE; -} - -void cleanup_skins() -{ - skin_destroy(active_skin); - active_skin = nullptr; - - gtk_widget_destroy (mainwin); - mainwin = nullptr; - gtk_widget_destroy (playlistwin); - playlistwin = nullptr; - gtk_widget_destroy (equalizerwin); - equalizerwin = nullptr; -} - -static void skin_load_viscolor (Skin * skin, const char * path) -{ - memcpy (skin->vis_colors, default_vis_colors, sizeof skin->vis_colors); - - VFSFile file = open_local_file_nocase (path, "viscolor.txt"); - if (! file) - return; - - Index<char> buffer = file.read_all (); - buffer.append (0); /* null-terminated */ - - char * string = buffer.begin (); - - for (int line = 0; string && line < 24; line ++) - { - char * next = text_parse_line (string); - GArray * array = string_to_garray (string); - - if (array->len >= 3) - skin->vis_colors[line] = COLOR (g_array_index (array, int, 0), - g_array_index (array, int, 1), g_array_index (array, int, 2)); - - g_array_free (array, TRUE); - string = next; - } -} - -static void -skin_numbers_generate_dash(Skin * skin) -{ - g_return_if_fail(skin != nullptr); - - cairo_surface_t * old = skin->pixmaps[SKIN_NUMBERS]; - if (! old || cairo_image_surface_get_width (old) < 99) - return; - - int h = cairo_image_surface_get_height (old); - cairo_surface_t * surface = surface_new (108, h); - - surface_copy_rect (old, 0, 0, 99, h, surface, 0, 0); - surface_copy_rect (old, 90, 0, 9, h, surface, 99, 0); - surface_copy_rect (old, 20, 6, 5, 1, surface, 101, 6); - - cairo_surface_destroy (old); - skin->pixmaps[SKIN_NUMBERS] = surface; -} - -static gboolean -skin_load_pixmaps(Skin * skin, const char * path) -{ - AUDDBG("Loading pixmaps in %s\n", path); - - for (int i = 0; i < SKIN_PIXMAP_COUNT; i++) - if (! skin_load_pixmap_id (skin, (SkinPixmapId) i, path)) - return FALSE; - - if (skin->pixmaps[SKIN_TEXT]) - skin_get_textcolors (skin, skin->pixmaps[SKIN_TEXT]); - - if (skin->pixmaps[SKIN_NUMBERS] && cairo_image_surface_get_width - (skin->pixmaps[SKIN_NUMBERS]) < 108) - skin_numbers_generate_dash (skin); - - skin_load_pl_colors (skin, path); - skin_load_viscolor (skin, path); - - return TRUE; -} - -/** - * Checks if all pixmap files exist that skin needs. - */ -static gboolean -skin_check_pixmaps(const Skin * skin, const char * skin_path) -{ - unsigned i; - for (i = 0; i < SKIN_PIXMAP_COUNT; i++) - { - char *filename = skin_pixmap_locate_basenames(skin, - skin_pixmap_id_lookup(i), - skin_path); - if (!filename) - return FALSE; - g_free(filename); - } - return TRUE; -} - -static gboolean -skin_load_nolock(Skin * skin, const char * path, gboolean force) -{ - char *newpath, *skin_path; - int archive = 0; - - AUDDBG("Attempt to load skin \"%s\"\n", path); - - g_return_val_if_fail(skin != nullptr, FALSE); - g_return_val_if_fail(path != nullptr, FALSE); - - if (! g_file_test (path, G_FILE_TEST_EXISTS)) - return FALSE; - - if(force) AUDDBG("reloading forced!\n"); - if (!force && skin->path && !strcmp(skin->path, path)) { - AUDDBG("skin %s already loaded\n", path); - return FALSE; - } - - if (file_is_archive(path)) { - AUDDBG("Attempt to load archive\n"); - if (!(skin_path = archive_decompress(path))) { - AUDDBG("Unable to extract skin archive (%s)\n", path); - return FALSE; - } - archive = 1; - } else { - skin_path = g_strdup(path); - } - - // Check if skin path has all necessary files. - if (!skin_check_pixmaps(skin, skin_path)) { - if(archive) del_directory(skin_path); - AUDDBG("Skin path (%s) doesn't have all wanted pixmaps\n", skin_path); - g_free(skin_path); - return FALSE; - } - - // skin_free() frees skin->path and variable path can actually be skin->path - // and we want to get the path before possibly freeing it. - newpath = g_strdup(path); - skin_free(skin); - skin->path = newpath; - - skin_load_hints (skin, skin_path); - - if (!skin_load_pixmaps(skin, skin_path)) { - if(archive) del_directory(skin_path); - g_free(skin_path); - AUDDBG("Skin loading failed\n"); - return FALSE; - } - - GdkRegion * masks[SKIN_MASK_COUNT]; - skin_load_masks (skin, skin_path, masks); - window_set_shapes (mainwin, masks[SKIN_MASK_MAIN], masks[SKIN_MASK_MAIN_SHADE]); - window_set_shapes (equalizerwin, masks[SKIN_MASK_EQ], masks[SKIN_MASK_EQ_SHADE]); - - if(archive) del_directory(skin_path); - g_free(skin_path); - - return TRUE; -} - -void skin_install_skin (const char * path) -{ - GError * err = 0; - char * data; - size_t len; - - if (! g_file_get_contents (path, & data, & len, & err)) - { - AUDERR ("Failed to read %s: %s\n", path, err->message); - g_error_free (err); - return; - } - - make_directory (skins_paths[SKINS_PATH_USER_SKIN_DIR]); - - char * base = g_path_get_basename (path); - char * target = g_build_filename (skins_paths[SKINS_PATH_USER_SKIN_DIR], base, nullptr); - - if (! g_file_set_contents (target, data, len, & err)) - { - AUDERR ("Failed to write %s: %s\n", path, err->message); - g_error_free (err); - g_free (data); - g_free (base); - g_free (target); - return; - } - - g_free (data); - g_free (base); - g_free (target); -} - -static gboolean skin_load (Skin * skin, const char * path) -{ - gboolean ret; - - g_return_val_if_fail(skin != nullptr, FALSE); - - if (!path) - return FALSE; - - ret = skin_load_nolock(skin, path, FALSE); - - if(!ret) { - AUDDBG("loading failed\n"); - return FALSE; /* don't try to update anything if loading failed --asphyx */ - } - - if (skin->pixmaps[SKIN_NUMBERS]) - { - int h = cairo_image_surface_get_height (skin->pixmaps[SKIN_NUMBERS]); - ui_skinned_number_set_size (mainwin_minus_num, 9, h); - ui_skinned_number_set_size (mainwin_10min_num, 9, h); - ui_skinned_number_set_size (mainwin_min_num, 9, h); - ui_skinned_number_set_size (mainwin_10sec_num, 9, h); - ui_skinned_number_set_size (mainwin_sec_num, 9, h); - } - - if (skin->pixmaps[SKIN_PLAYPAUSE]) - ui_skinned_playstatus_set_size (mainwin_playstatus, 11, - cairo_image_surface_get_height (skin->pixmaps[SKIN_PLAYPAUSE])); - - // hide the menurow if it is not present in the skin - if (cairo_image_surface_get_width (skin->pixmaps[SKIN_TITLEBAR]) < 344) - skin->properties.mainwin_menurow_visible = false; - - // hide the equalizer graph if we have a short eqmain.bmp - gtk_widget_set_visible (equalizerwin_graph, - cairo_image_surface_get_height (skin->pixmaps[SKIN_EQMAIN]) >= 315); - - return TRUE; -} - -void skin_draw_pixbuf (cairo_t * cr, SkinPixmapId id, int xsrc, int ysrc, int - xdest, int ydest, int width, int height) -{ - if (! active_skin->pixmaps[id]) - return; - - cairo_save (cr); - cairo_scale (cr, config.scale, config.scale); - cairo_set_source_surface (cr, active_skin->pixmaps[id], xdest - xsrc, ydest - ysrc); - cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST); - cairo_rectangle (cr, xdest, ydest, width, height); - cairo_fill (cr); - cairo_restore (cr); -} - -void skin_get_eq_spline_colors (Skin * skin, uint32_t colors[19]) -{ - if (! skin->pixmaps[SKIN_EQMAIN]) - { - memset (colors, 0, sizeof (uint32_t) * 19); - return; - } - - for (int i = 0; i < 19; i ++) - colors[i] = surface_get_pixel (skin->pixmaps[SKIN_EQMAIN], 115, i + 294); -} - -static void skin_draw_playlistwin_frame_top (cairo_t * cr, int width, int - height, gboolean focus) -{ - /* The title bar skin consists of 2 sets of 4 images, 1 set - * for focused state and the other for unfocused. The 4 images - * are: - * - * a. right corner (25,20) - * b. left corner (25,20) - * c. tiler (25,20) - * d. title (100,20) - * - * min allowed width = 100+25+25 = 150 - */ - - int i, y, c; - - /* get y offset of the pixmap set to use */ - if (focus) - y = 0; - else - y = 21; - - /* left corner */ - skin_draw_pixbuf (cr, SKIN_PLEDIT, 0, y, 0, 0, 25, 20); - - /* titlebar title */ - skin_draw_pixbuf (cr, SKIN_PLEDIT, 26, y, (width - 100) / 2, 0, 100, 20); - - /* titlebar right corner */ - skin_draw_pixbuf (cr, SKIN_PLEDIT, 153, y, width - 25, 0, 25, 20); - - /* tile draw the remaining frame */ - - /* compute tile count */ - c = (width - (100 + 25 + 25)) / 25; - - for (i = 0; i < c / 2; i++) { - /* left of title */ - skin_draw_pixbuf (cr, SKIN_PLEDIT, 127, y, 25 + i * 25, 0, 25, 20); - - /* right of title */ - skin_draw_pixbuf (cr, SKIN_PLEDIT, 127, y, (width + 100) / 2 + i * 25, - 0, 25, 20); - } - - if (c & 1) { - /* Odd tile count, so one remaining to draw. Here we split - * it into two and draw half on either side of the title */ - skin_draw_pixbuf (cr, SKIN_PLEDIT, 127, y, ((c / 2) * 25) + 25, 0, 12, - 20); - skin_draw_pixbuf (cr, SKIN_PLEDIT, 127, y, (width / 2) + ((c / 2) * 25) - + 50, 0, 13, 20); - } -} - -static void skin_draw_playlistwin_frame_bottom (cairo_t * cr, int width, int - height, gboolean focus) -{ - /* The bottom frame skin consists of 1 set of 4 images. The 4 - * images are: - * - * a. left corner with menu buttons (125,38) - * b. visualization window (75,38) - * c. right corner with play buttons (150,38) - * d. frame tile (25,38) - * - * (min allowed width = 125+150+25=300 - */ - - int i, c; - - /* bottom left corner (menu buttons) */ - skin_draw_pixbuf (cr, SKIN_PLEDIT, 0, 72, 0, height - 38, 125, 38); - - c = (width - 275) / 25; - - /* draw visualization window, if width allows */ - if (c >= 3) { - c -= 3; - skin_draw_pixbuf (cr, SKIN_PLEDIT, 205, 0, width - (150 + 75), height - - 38, 75, 38); - } - - /* Bottom right corner (playbuttons etc) */ - skin_draw_pixbuf (cr, SKIN_PLEDIT, 126, 72, width - 150, height - 38, 150, - 38); - - /* Tile draw the remaining undrawn portions */ - for (i = 0; i < c; i++) - skin_draw_pixbuf (cr, SKIN_PLEDIT, 179, 0, 125 + i * 25, height - 38, - 25, 38); -} - -static void skin_draw_playlistwin_frame_sides (cairo_t * cr, int width, int - height, gboolean focus) -{ - /* The side frames consist of 2 tile images. 1 for the left, 1 for - * the right. - * a. left (12,29) - * b. right (19,29) - */ - - int i; - - /* frame sides */ - for (i = 0; i < (height - (20 + 38)) / 29; i++) { - /* left */ - skin_draw_pixbuf (cr, SKIN_PLEDIT, 0, 42, 0, 20 + i * 29, 12, 29); - - /* right */ - skin_draw_pixbuf (cr, SKIN_PLEDIT, 32, 42, width - 19, 20 + i * 29, 19, - 29); - } -} - -void skin_draw_playlistwin_frame (cairo_t * cr, int width, int height, - gboolean focus) -{ - skin_draw_playlistwin_frame_top (cr, width, height, focus); - skin_draw_playlistwin_frame_bottom (cr, width, height, focus); - skin_draw_playlistwin_frame_sides (cr, width, height, focus); -} - -void skin_draw_playlistwin_shaded (cairo_t * cr, int width, gboolean focus) -{ - /* The shade mode titlebar skin consists of 4 images: - * a) left corner offset (72,42) size (25,14) - * b) right corner, focused offset (99,57) size (50,14) - * c) right corner, unfocused offset (99,42) size (50,14) - * d) bar tile offset (72,57) size (25,14) - */ - - int i; - - /* left corner */ - skin_draw_pixbuf (cr, SKIN_PLEDIT, 72, 42, 0, 0, 25, 14); - - /* bar tile */ - for (i = 0; i < (width - 75) / 25; i++) - skin_draw_pixbuf (cr, SKIN_PLEDIT, 72, 57, (i * 25) + 25, 0, 25, 14); - - /* right corner */ - skin_draw_pixbuf (cr, SKIN_PLEDIT, 99, focus ? 42 : 57, width - 50, 0, 50, - 14); -} - -void skin_draw_mainwin_titlebar (cairo_t * cr, gboolean shaded, gboolean focus) -{ - /* The titlebar skin consists of 2 sets of 2 images, one for for - * shaded and the other for unshaded mode, giving a total of 4. - * The images are exactly 275x14 pixels, aligned and arranged - * vertically on each other in the pixmap in the following order: - * - * a) unshaded, focused offset (27, 0) - * b) unshaded, unfocused offset (27, 15) - * c) shaded, focused offset (27, 29) - * d) shaded, unfocused offset (27, 42) - */ - - int y_offset; - - if (shaded) { - if (focus) - y_offset = 29; - else - y_offset = 42; - } - else { - if (focus) - y_offset = 0; - else - y_offset = 15; - } - - skin_draw_pixbuf (cr, SKIN_TITLEBAR, 27, y_offset, 0, 0, - active_skin->properties.mainwin_width, MAINWIN_TITLEBAR_HEIGHT); -} diff --git a/src/skins/ui_skin_load_ini.cc b/src/skins/ui_skin_load_ini.cc deleted file mode 100644 index ae49764..0000000 --- a/src/skins/ui_skin_load_ini.cc +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Audacious - * Copyright 2011-2013 Audacious development team - * - * 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; under version 3 of the License. - * - * 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 <http://www.gnu.org/licenses>. - * - * The Audacious team does not consider modular code linking to - * Audacious or using our public API to be a derived work. - */ - -#include <stdlib.h> - -#include <libaudcore/inifile.h> - -#include "skins_cfg.h" -#include "ui_skin.h" -#include "util.h" - -/* - * skin.hints parsing - */ - -typedef struct { - const char * name; - int * value_ptr; -} HintPair; - -const SkinProperties skin_default_hints = SkinProperties (); - -/* so we can use static addresses in the table below */ -static SkinProperties static_hints; - -/* in alphabetical order to allow binary search */ -static const HintPair hint_pairs[] = { - {"mainwinaboutx", & static_hints.mainwin_about_x}, - {"mainwinabouty", & static_hints.mainwin_about_y}, - {"mainwinbalancex", & static_hints.mainwin_balance_x}, - {"mainwinbalancey", & static_hints.mainwin_balance_y}, - {"mainwinclosex", & static_hints.mainwin_close_x}, - {"mainwinclosey", & static_hints.mainwin_close_y}, - {"mainwinejectx", & static_hints.mainwin_eject_x}, - {"mainwinejecty", & static_hints.mainwin_eject_y}, - {"mainwineqbuttonx", & static_hints.mainwin_eqbutton_x}, - {"mainwineqbuttony", & static_hints.mainwin_eqbutton_y}, - {"mainwinheight", & static_hints.mainwin_height}, - {"mainwininfobarx", & static_hints.mainwin_infobar_x}, - {"mainwininfobary", & static_hints.mainwin_infobar_y}, - {"mainwinmenurowvisible", & static_hints.mainwin_menurow_visible}, - {"mainwinminimizex", & static_hints.mainwin_minimize_x}, - {"mainwinminimizey", & static_hints.mainwin_minimize_y}, - {"mainwinnextx", & static_hints.mainwin_next_x}, - {"mainwinnexty", & static_hints.mainwin_next_y}, - {"mainwinnumber0x", & static_hints.mainwin_number_0_x}, - {"mainwinnumber0y", & static_hints.mainwin_number_0_y}, - {"mainwinnumber1x", & static_hints.mainwin_number_1_x}, - {"mainwinnumber1y", & static_hints.mainwin_number_1_y}, - {"mainwinnumber2x", & static_hints.mainwin_number_2_x}, - {"mainwinnumber2y", & static_hints.mainwin_number_2_y}, - {"mainwinnumber3x", & static_hints.mainwin_number_3_x}, - {"mainwinnumber3y", & static_hints.mainwin_number_3_y}, - {"mainwinnumber4x", & static_hints.mainwin_number_4_x}, - {"mainwinnumber4y", & static_hints.mainwin_number_4_y}, - {"mainwinothertextisstatus", & static_hints.mainwin_othertext_is_status}, - {"mainwinothertextvisible", & static_hints.mainwin_othertext_visible}, - {"mainwinpausex", & static_hints.mainwin_pause_x}, - {"mainwinpausey", & static_hints.mainwin_pause_y}, - {"mainwinplaystatusx", & static_hints.mainwin_playstatus_x}, - {"mainwinplaystatusy", & static_hints.mainwin_playstatus_y}, - {"mainwinplayx", & static_hints.mainwin_play_x}, - {"mainwinplayy", & static_hints.mainwin_play_y}, - {"mainwinplbuttonx", & static_hints.mainwin_plbutton_x}, - {"mainwinplbuttony", & static_hints.mainwin_plbutton_y}, - {"mainwinpositionx", & static_hints.mainwin_position_x}, - {"mainwinpositiony", & static_hints.mainwin_position_y}, - {"mainwinpreviousx", & static_hints.mainwin_previous_x}, - {"mainwinpreviousy", & static_hints.mainwin_previous_y}, - {"mainwinrepeatx", & static_hints.mainwin_repeat_x}, - {"mainwinrepeaty", & static_hints.mainwin_repeat_y}, - {"mainwinshadex", & static_hints.mainwin_shade_x}, - {"mainwinshadey", & static_hints.mainwin_shade_y}, - {"mainwinshufflex", & static_hints.mainwin_shuffle_x}, - {"mainwinshuffley", & static_hints.mainwin_shuffle_y}, - {"mainwinstopx", & static_hints.mainwin_stop_x}, - {"mainwinstopy", & static_hints.mainwin_stop_y}, - {"mainwinstreaminfovisible", & static_hints.mainwin_streaminfo_visible}, - {"mainwintextvisible", & static_hints.mainwin_text_visible}, - {"mainwintextwidth", & static_hints.mainwin_text_width}, - {"mainwintextx", & static_hints.mainwin_text_x}, - {"mainwintexty", & static_hints.mainwin_text_y}, - {"mainwinvisvisible", & static_hints.mainwin_vis_visible}, - {"mainwinvisx", & static_hints.mainwin_vis_x}, - {"mainwinvisy", & static_hints.mainwin_vis_y}, - {"mainwinvolumex", & static_hints.mainwin_volume_x}, - {"mainwinvolumey", & static_hints.mainwin_volume_y}, - {"mainwinwidth", & static_hints.mainwin_width}, - {"textboxbitmapfontheight", & static_hints.textbox_bitmap_font_height}, - {"textboxbitmapfontwidth", & static_hints.textbox_bitmap_font_width}, -}; - -static int hint_pair_compare (const void * key, const void * pair) -{ - return g_ascii_strcasecmp ((const char *) key, ((const HintPair *) pair)->name); -} - -class HintsParser : public IniParser -{ -private: - bool valid_heading = false; - - void handle_heading (const char * heading) - { valid_heading = ! g_ascii_strcasecmp (heading, "skin"); } - - void handle_entry (const char * key, const char * value) - { - if (! valid_heading) - return; - - HintPair * pair = (HintPair *) bsearch (key, hint_pairs, - aud::n_elems (hint_pairs), sizeof (HintPair), hint_pair_compare); - - if (pair) - * pair->value_ptr = atoi (value); - } -}; - -void skin_load_hints (Skin * skin, const char * path) -{ - static_hints = skin_default_hints; - - VFSFile file = open_local_file_nocase (path, "skin.hints"); - if (file) - HintsParser ().parse (file); - - skin->properties = static_hints; -} - -/* - * pledit.txt parsing - */ - -class PLColorsParser : public IniParser -{ -public: - PLColorsParser (Skin & skin) : - skin (skin), - valid_heading (false) {} - -private: - Skin & skin; - bool valid_heading; - - void handle_heading (const char * heading) - { valid_heading = ! g_ascii_strcasecmp (heading, "text"); } - - void handle_entry (const char * key, const char * value) - { - if (! valid_heading) - return; - - if (value[0] == '#') - value ++; - - uint32_t color = strtol (value, nullptr, 16); - - if (! g_ascii_strcasecmp (key, "normal")) - skin.colors[SKIN_PLEDIT_NORMAL] = color; - else if (! g_ascii_strcasecmp (key, "current")) - skin.colors[SKIN_PLEDIT_CURRENT] = color; - else if (! g_ascii_strcasecmp (key, "normalbg")) - skin.colors[SKIN_PLEDIT_NORMALBG] = color; - else if (! g_ascii_strcasecmp (key, "selectedbg")) - skin.colors[SKIN_PLEDIT_SELECTEDBG] = color; - } -}; - -void skin_load_pl_colors (Skin * skin, const char * path) -{ - skin->colors[SKIN_PLEDIT_NORMAL] = 0x2499ff; - skin->colors[SKIN_PLEDIT_CURRENT] = 0xffeeff; - skin->colors[SKIN_PLEDIT_NORMALBG] = 0x0a120a; - skin->colors[SKIN_PLEDIT_SELECTEDBG] = 0x0a124a; - - VFSFile file = open_local_file_nocase (path, "pledit.txt"); - if (file) - PLColorsParser (* skin).parse (file); -} - -/* - * region.txt parsing - */ - -class MaskParser : public IniParser -{ -public: - GArray * numpoints[SKIN_MASK_COUNT] {}; - GArray * pointlist[SKIN_MASK_COUNT] {}; - - ~MaskParser () - { - for (GArray * array : numpoints) - if (array) g_array_free (array, true); - for (GArray * array : pointlist) - if (array) g_array_free (array, true); - } - -private: - SkinMaskId current_id = SkinMaskId (-1); - - void handle_heading (const char * heading) - { - if (! g_ascii_strcasecmp (heading, "normal")) - current_id = SKIN_MASK_MAIN; - else if (! g_ascii_strcasecmp (heading, "windowshade")) - current_id = SKIN_MASK_MAIN_SHADE; - else if (! g_ascii_strcasecmp (heading, "equalizer")) - current_id = SKIN_MASK_EQ; - else if (! g_ascii_strcasecmp (heading, "equalizerws")) - current_id = SKIN_MASK_EQ_SHADE; - else - current_id = (SkinMaskId) -1; - } - - void handle_entry (const char * key, const char * value) - { - if (current_id == (SkinMaskId) -1) - return; - - if (! g_ascii_strcasecmp (key, "numpoints")) - { - if (! numpoints[current_id]) - numpoints[current_id] = string_to_garray (value); - } - else if (! g_ascii_strcasecmp (key, "pointlist")) - { - if (! pointlist[current_id]) - pointlist[current_id] = string_to_garray (value); - } - } -}; - -static GdkRegion * skin_create_mask (const GArray * num, - const GArray * point, int width, int height) -{ - if (! num || ! point) - return nullptr; - - width *= config.scale; - height *= config.scale; - - GdkRegion * mask = nullptr; - - unsigned j = 0; - for (unsigned i = 0; i < num->len; i ++) - { - int n_points = g_array_index (num, int, i); - if (n_points <= 0 || j + 2 * n_points > point->len) - break; - - int xmin = width, ymin = height, xmax = 0, ymax = 0; - - for (int k = 0; k < n_points; k ++) - { - int x = g_array_index (point, int, j + k * 2) * config.scale; - int y = g_array_index (point, int, j + k * 2 + 1) * config.scale; - - xmin = aud::min (xmin, x); - ymin = aud::min (ymin, y); - xmax = aud::max (xmax, x); - ymax = aud::max (ymax, y); - } - - if (xmax > xmin && ymax > ymin) - { - GdkRectangle rect = {xmin, ymin, xmax - xmin, ymax - ymin}; - - if (mask) - gdk_region_union_with_rect (mask, & rect); - else - mask = gdk_region_rectangle (& rect); - } - - j += n_points * 2; - } - - return mask; -} - -void skin_load_masks (Skin * skin, const char * path, GdkRegion * masks[SKIN_MASK_COUNT]) -{ - int sizes[SKIN_MASK_COUNT][2] = { - {skin->properties.mainwin_width, skin->properties.mainwin_height}, - {275, 16}, - {275, 116}, - {275, 16} - }; - - MaskParser parser; - VFSFile file = open_local_file_nocase (path, "region.txt"); - if (file) - parser.parse (file); - - for (int id = 0; id < SKIN_MASK_COUNT; id ++) - masks[id] = skin_create_mask (parser.numpoints[id], - parser.pointlist[id], sizes[id][0], sizes[id][1]); -} diff --git a/src/skins/ui_skinned_button.cc b/src/skins/ui_skinned_button.cc deleted file mode 100644 index 93f33cf..0000000 --- a/src/skins/ui_skinned_button.cc +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Audacious - a cross-platform multimedia player - * Copyright (c) 2007 Tomasz Moń - * Copyright (c) 2011 John Lindgren - * - * 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; under version 3 of the License. - * - * 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 <http://www.gnu.org/licenses>. - * - * The Audacious team does not consider modular code linking to - * Audacious or using our public API to be a derived work. - */ - -#include "draw-compat.h" -#include "skins_cfg.h" -#include "ui_skinned_button.h" - -enum {BUTTON_TYPE_NORMAL, BUTTON_TYPE_TOGGLE, BUTTON_TYPE_SMALL}; - -typedef struct { - int type; - int w, h; - int nx, ny, px, py; - int pnx, pny, ppx, ppy; - SkinPixmapId si1, si2; - gboolean pressed, rpressed, active; - ButtonCB on_press, on_release, on_rpress, on_rrelease; -} ButtonData; - -DRAW_FUNC_BEGIN (button_draw) - ButtonData * data = (ButtonData *) g_object_get_data ((GObject *) wid, "buttondata"); - g_return_val_if_fail (data, FALSE); - - switch (data->type) - { - case BUTTON_TYPE_NORMAL: - if (data->pressed) - skin_draw_pixbuf (cr, data->si2, data->px, data->py, 0, 0, data->w, data->h); - else - skin_draw_pixbuf (cr, data->si1, data->nx, data->ny, 0, 0, data->w, data->h); - break; - case BUTTON_TYPE_TOGGLE: - if (data->active) - { - if (data->pressed) - skin_draw_pixbuf (cr, data->si2, data->ppx, data->ppy, 0, 0, data->w, data->h); - else - skin_draw_pixbuf (cr, data->si1, data->pnx, data->pny, 0, 0, data->w, data->h); - } - else - { - if (data->pressed) - skin_draw_pixbuf (cr, data->si2, data->px, data->py, 0, 0, data->w, data->h); - else - skin_draw_pixbuf (cr, data->si1, data->nx, data->ny, 0, 0, data->w, data->h); - } - break; - } -DRAW_FUNC_END - -static gboolean button_press (GtkWidget * button, GdkEventButton * event) -{ - ButtonData * data = (ButtonData *) g_object_get_data ((GObject *) button, "buttondata"); - g_return_val_if_fail (data, FALSE); - - /* pass events through to the parent widget only if neither the press nor - * release signals are connected; sending one and not the other causes - * problems (in particular with dragging windows around) */ - if (event->button == 1 && (data->on_press || data->on_release)) - { - data->pressed = TRUE; - if (data->on_press) - data->on_press (button, event); - } - else if (event->button == 3 && (data->on_rpress || data->on_rrelease)) - { - data->rpressed = TRUE; - if (data->on_rpress) - data->on_rpress (button, event); - } - else - return FALSE; - - if (data->type != BUTTON_TYPE_SMALL) - gtk_widget_queue_draw (button); - - return TRUE; -} - -static gboolean button_release (GtkWidget * button, GdkEventButton * event) -{ - ButtonData * data = (ButtonData *) g_object_get_data ((GObject *) button, "buttondata"); - g_return_val_if_fail (data, FALSE); - - if (event->button == 1 && (data->on_press || data->on_release)) - { - if (! data->pressed) - return TRUE; - - data->pressed = FALSE; - if (data->type == BUTTON_TYPE_TOGGLE) - data->active = ! data->active; - if (data->on_release) - data->on_release (button, event); - } - else if (event->button == 3 && (data->on_rpress || data->on_rrelease)) - { - if (! data->rpressed) - return TRUE; - - data->rpressed = FALSE; - if (data->on_rrelease) - data->on_rrelease (button, event); - } - else - return FALSE; - - if (data->type != BUTTON_TYPE_SMALL) - gtk_widget_queue_draw (button); - - return TRUE; -} - -static void button_destroy (GtkWidget * button) -{ - g_free (g_object_get_data ((GObject *) button, "buttondata")); -} - -static GtkWidget * button_new_base (int type, int w, int h) -{ - GtkWidget * button; - - if (type == BUTTON_TYPE_SMALL) - { - button = gtk_event_box_new (); - gtk_event_box_set_visible_window ((GtkEventBox *) button, FALSE); - } - else - button = gtk_drawing_area_new (); - - gtk_widget_set_size_request (button, w * config.scale, h * config.scale); - gtk_widget_add_events (button, GDK_BUTTON_PRESS_MASK | - GDK_BUTTON_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK); - - if (type != BUTTON_TYPE_SMALL) - DRAW_CONNECT (button, button_draw); - - g_signal_connect (button, "button-press-event", (GCallback) button_press, - nullptr); - g_signal_connect (button, "button-release-event", (GCallback) - button_release, nullptr); - g_signal_connect (button, "destroy", (GCallback) button_destroy, nullptr); - - ButtonData * data = g_new0 (ButtonData, 1); - data->type = type; - data->w = w; - data->h = h; - g_object_set_data ((GObject *) button, "buttondata", data); - - return button; -} - -GtkWidget * button_new (int w, int h, int nx, int ny, int px, int py, - SkinPixmapId si1, SkinPixmapId si2) -{ - GtkWidget * button = button_new_base (BUTTON_TYPE_NORMAL, w, h); - ButtonData * data = (ButtonData *) g_object_get_data ((GObject *) button, "buttondata"); - g_return_val_if_fail (data, nullptr); - - data->nx = nx; - data->ny = ny; - data->px = px; - data->py = py; - data->si1 = si1; - data->si2 = si2; - - return button; -} - -GtkWidget * button_new_toggle (int w, int h, int nx, int ny, int px, int - py, int pnx, int pny, int ppx, int ppy, SkinPixmapId si1, SkinPixmapId si2) -{ - GtkWidget * button = button_new_base (BUTTON_TYPE_TOGGLE, w, h); - ButtonData * data = (ButtonData *) g_object_get_data ((GObject *) button, "buttondata"); - g_return_val_if_fail (data, nullptr); - - data->nx = nx; - data->ny = ny; - data->px = px; - data->py = py; - data->pnx = pnx; - data->pny = pny; - data->ppx = ppx; - data->ppy = ppy; - data->si1 = si1; - data->si2 = si2; - - return button; -} - -GtkWidget * button_new_small (int w, int h) -{ - return button_new_base (BUTTON_TYPE_SMALL, w, h); -} - -void button_on_press (GtkWidget * button, ButtonCB callback) -{ - ButtonData * data = (ButtonData *) g_object_get_data ((GObject *) button, "buttondata"); - g_return_if_fail (data); - - data->on_press = callback; -} - -void button_on_release (GtkWidget * button, ButtonCB callback) -{ - ButtonData * data = (ButtonData *) g_object_get_data ((GObject *) button, "buttondata"); - g_return_if_fail (data); - - data->on_release = callback; -} - -void button_on_rpress (GtkWidget * button, ButtonCB callback) -{ - ButtonData * data = (ButtonData *) g_object_get_data ((GObject *) button, "buttondata"); - g_return_if_fail (data); - - data->on_rpress = callback; -} - -void button_on_rrelease (GtkWidget * button, ButtonCB callback) -{ - ButtonData * data = (ButtonData *) g_object_get_data ((GObject *) button, "buttondata"); - g_return_if_fail (data); - - data->on_rrelease = callback; -} - -gboolean button_get_active (GtkWidget * button) -{ - ButtonData * data = (ButtonData *) g_object_get_data ((GObject *) button, "buttondata"); - g_return_val_if_fail (data && data->type == BUTTON_TYPE_TOGGLE, FALSE); - - return data->active; -} - -void button_set_active (GtkWidget * button, gboolean active) -{ - ButtonData * data = (ButtonData *) g_object_get_data ((GObject *) button, "buttondata"); - g_return_if_fail (data && data->type == BUTTON_TYPE_TOGGLE); - - if (data->active == active) - return; - - data->active = active; - gtk_widget_queue_draw (button); -} diff --git a/src/skins/ui_skinned_button.h b/src/skins/ui_skinned_button.h deleted file mode 100644 index 47c0093..0000000 --- a/src/skins/ui_skinned_button.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Audacious - a cross-platform multimedia player - * Copyright (c) 2007 Tomasz Moń - * Copyright (c) 2011 John Lindgren - * - * 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; under version 3 of the License. - * - * 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 <http://www.gnu.org/licenses>. - * - * The Audacious team does not consider modular code linking to - * Audacious or using our public API to be a derived work. - */ - -#ifndef SKINS_UI_SKINNED_BUTTON_H -#define SKINS_UI_SKINNED_BUTTON_H - -#include <gtk/gtk.h> - -#include "ui_skin.h" - -typedef void (* ButtonCB) (GtkWidget * button, GdkEventButton * event); - -GtkWidget * button_new (int w, int h, int nx, int ny, int px, - int py, SkinPixmapId si1, SkinPixmapId si2); -GtkWidget * button_new_toggle (int w, int h, int nx, int ny, - int px, int py, int pnx, int pny, int ppx, int ppy, SkinPixmapId si1, - SkinPixmapId si2); -GtkWidget * button_new_small (int w, int h); - -void button_on_press (GtkWidget * button, ButtonCB callback); -void button_on_release (GtkWidget * button, ButtonCB callback); -void button_on_rpress (GtkWidget * button, ButtonCB callback); -void button_on_rrelease (GtkWidget * button, ButtonCB callback); - -gboolean button_get_active (GtkWidget * button); -void button_set_active (GtkWidget * button, gboolean active); - -#endif diff --git a/src/skins/ui_skinned_equalizer_slider.cc b/src/skins/ui_skinned_equalizer_slider.cc deleted file mode 100644 index 69fffab..0000000 --- a/src/skins/ui_skinned_equalizer_slider.cc +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Audacious - a cross-platform multimedia player - * Copyright (c) 2007 Tomasz Moń - * Copyright (c) 2011 John Lindgren - * - * Based on: - * BMP - Cross-platform multimedia player - * Copyright (C) 2003-2004 BMP development team. - * XMMS: - * Copyright (C) 1998-2003 XMMS development team. - * - * 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; under version 3 of the License. - * - * 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 <http://www.gnu.org/licenses>. - */ - -#include <libaudcore/i18n.h> - -#include "draw-compat.h" -#include "skins_cfg.h" -#include "ui_equalizer.h" -#include "ui_main.h" -#include "ui_skin.h" -#include "ui_skinned_equalizer_slider.h" - -typedef struct { - char * name; - int pos; - float val; - gboolean pressed; -} EqSliderData; - -DRAW_FUNC_BEGIN (eq_slider_draw) - EqSliderData * data = (EqSliderData *) g_object_get_data ((GObject *) wid, "eqsliderdata"); - g_return_val_if_fail (data, FALSE); - - int frame = 27 - data->pos * 27 / 50; - if (frame < 14) - skin_draw_pixbuf (cr, SKIN_EQMAIN, 13 + 15 * frame, 164, 0, 0, 14, 63); - else - skin_draw_pixbuf (cr, SKIN_EQMAIN, 13 + 15 * (frame - 14), 229, 0, 0, - 14, 63); - - if (data->pressed) - skin_draw_pixbuf (cr, SKIN_EQMAIN, 0, 176, 1, data->pos, 11, 11); - else - skin_draw_pixbuf (cr, SKIN_EQMAIN, 0, 164, 1, data->pos, 11, 11); -DRAW_FUNC_END - -static void eq_slider_moved (EqSliderData * data, int pos) -{ - data->pos = aud::clamp (pos, 0, 50); - if (data->pos == 24 || data->pos == 26) - data->pos = 25; - - data->val = (float) (25 - data->pos) * AUD_EQ_MAX_GAIN / 25; - - equalizerwin_eq_changed (); - - char buf[100]; - snprintf (buf, sizeof buf, "%s: %+.1f dB", data->name, data->val); - mainwin_show_status_message (buf); -} - -static gboolean eq_slider_button_press (GtkWidget * slider, GdkEventButton * - event) -{ - EqSliderData * data = (EqSliderData *) g_object_get_data ((GObject *) slider, "eqsliderdata"); - g_return_val_if_fail (data, FALSE); - - if (event->button != 1) - return FALSE; - - data->pressed = TRUE; - - eq_slider_moved (data, event->y / config.scale - 5); - gtk_widget_queue_draw (slider); - return TRUE; -} - -static gboolean eq_slider_button_release (GtkWidget * slider, GdkEventButton * - event) -{ - EqSliderData * data = (EqSliderData *) g_object_get_data ((GObject *) slider, "eqsliderdata"); - g_return_val_if_fail (data, FALSE); - - if (event->button != 1) - return FALSE; - - if (! data->pressed) - return TRUE; - - data->pressed = FALSE; - - eq_slider_moved (data, event->y / config.scale - 5); - gtk_widget_queue_draw (slider); - return TRUE; -} - -static gboolean eq_slider_motion (GtkWidget * slider, GdkEventMotion * event) -{ - EqSliderData * data = (EqSliderData *) g_object_get_data ((GObject *) slider, "eqsliderdata"); - g_return_val_if_fail (data, FALSE); - - if (! data->pressed) - return TRUE; - - eq_slider_moved (data, event->y / config.scale - 5); - gtk_widget_queue_draw (slider); - return TRUE; -} - -static gboolean eq_slider_scroll (GtkWidget * slider, GdkEventScroll * event) -{ - EqSliderData * data = (EqSliderData *) g_object_get_data ((GObject *) slider, "eqsliderdata"); - g_return_val_if_fail (data, FALSE); - - if (event->direction == GDK_SCROLL_UP) - eq_slider_moved (data, data->pos - 2); - else - eq_slider_moved (data, data->pos + 2); - - gtk_widget_queue_draw (slider); - return TRUE; -} - -void eq_slider_set_val (GtkWidget * slider, float val) -{ - EqSliderData * data = (EqSliderData *) g_object_get_data ((GObject *) slider, "eqsliderdata"); - g_return_if_fail (data); - - if (data->pressed) - return; - - data->val = val; - data->pos = 25 - (int) (val * 25 / AUD_EQ_MAX_GAIN); - data->pos = aud::clamp (data->pos, 0, 50); - - gtk_widget_queue_draw (slider); -} - -float eq_slider_get_val (GtkWidget * slider) -{ - EqSliderData * data = (EqSliderData *) g_object_get_data ((GObject *) slider, "eqsliderdata"); - g_return_val_if_fail (data, 0); - - return data->val; -} - -static void eq_slider_destroy (GtkWidget * slider) -{ - EqSliderData * data = (EqSliderData *) g_object_get_data ((GObject *) slider, "eqsliderdata"); - g_return_if_fail (data); - - g_free (data->name); - g_free (data); -} - -GtkWidget * eq_slider_new (const char * name) -{ - GtkWidget * slider = gtk_drawing_area_new (); - gtk_widget_set_size_request (slider, 14 * config.scale, 63 * config.scale); - gtk_widget_add_events (slider, GDK_BUTTON_PRESS_MASK | - GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_SCROLL_MASK); - - DRAW_CONNECT (slider, eq_slider_draw); - - g_signal_connect (slider, "button-press-event", (GCallback) - eq_slider_button_press, nullptr); - g_signal_connect (slider, "button-release-event", (GCallback) - eq_slider_button_release, nullptr); - g_signal_connect (slider, "motion-notify-event", (GCallback) - eq_slider_motion, nullptr); - g_signal_connect (slider, "scroll-event", (GCallback) eq_slider_scroll, - nullptr); - g_signal_connect (slider, "destroy", (GCallback) eq_slider_destroy, nullptr); - - EqSliderData * data = g_new0 (EqSliderData, 1); - data->name = g_strdup (name); - g_object_set_data ((GObject *) slider, "eqsliderdata", data); - - return slider; -} diff --git a/src/skins/ui_skinned_horizontal_slider.cc b/src/skins/ui_skinned_horizontal_slider.cc deleted file mode 100644 index 8e52304..0000000 --- a/src/skins/ui_skinned_horizontal_slider.cc +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Audacious - a cross-platform multimedia player - * Copyright (c) 2007 Tomasz Moń - * Copyright (c) 2011 John Lindgren - * - * Based on: - * BMP - Cross-platform multimedia player - * Copyright (C) 2003-2004 BMP development team. - * XMMS: - * Copyright (C) 1998-2003 XMMS development team. - * - * 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; under version 3 of the License. - * - * 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 <http://www.gnu.org/licenses>. - * - * The Audacious team does not consider modular code linking to - * Audacious or using our public API to be a derived work. - */ - -#include <libaudcore/objects.h> - -#include "draw-compat.h" -#include "skins_cfg.h" -#include "ui_skin.h" -#include "ui_skinned_horizontal_slider.h" - -typedef struct { - int min, max, pos; - gboolean pressed; - SkinPixmapId si; - int w, h; - int fx, fy; - int kw, kh; - int knx, kny, kpx, kpy; - void (* on_motion) (void); - void (* on_release) (void); -} HSliderData; - -DRAW_FUNC_BEGIN (hslider_draw) - HSliderData * data = (HSliderData *) g_object_get_data ((GObject *) wid, "hsliderdata"); - g_return_val_if_fail (data, FALSE); - - skin_draw_pixbuf (cr, data->si, data->fx, data->fy, 0, 0, data->w, data->h); - - if (data->pressed) - skin_draw_pixbuf (cr, data->si, data->kpx, data->kpy, data->pos, - (data->h - data->kh) / 2, data->kw, data->kh); - else - skin_draw_pixbuf (cr, data->si, data->knx, data->kny, data->pos, - (data->h - data->kh) / 2, data->kw, data->kh); -DRAW_FUNC_END - -static gboolean hslider_button_press (GtkWidget * hslider, GdkEventButton * - event) -{ - HSliderData * data = (HSliderData *) g_object_get_data ((GObject *) hslider, "hsliderdata"); - g_return_val_if_fail (data, FALSE); - - if (event->button != 1) - return FALSE; - - data->pressed = TRUE; - data->pos = event->x / config.scale - data->kw / 2; - data->pos = aud::clamp (data->pos, data->min, data->max); - - if (data->on_motion) - data->on_motion (); - - gtk_widget_queue_draw (hslider); - return TRUE; -} - -static gboolean hslider_button_release (GtkWidget * hslider, GdkEventButton * - event) -{ - HSliderData * data = (HSliderData *) g_object_get_data ((GObject *) hslider, "hsliderdata"); - g_return_val_if_fail (data, FALSE); - - if (event->button != 1) - return FALSE; - - if (! data->pressed) - return TRUE; - - data->pressed = FALSE; - data->pos = event->x / config.scale - data->kw / 2; - data->pos = aud::clamp (data->pos, data->min, data->max); - - if (data->on_release) - data->on_release (); - - gtk_widget_queue_draw (hslider); - return TRUE; -} - -static gboolean hslider_motion_notify (GtkWidget * hslider, GdkEventMotion * - event) -{ - HSliderData * data = (HSliderData *) g_object_get_data ((GObject *) hslider, "hsliderdata"); - g_return_val_if_fail (data, FALSE); - - if (! data->pressed) - return TRUE; - - data->pressed = TRUE; - data->pos = event->x / config.scale - data->kw / 2; - data->pos = aud::clamp (data->pos, data->min, data->max); - - if (data->on_motion) - data->on_motion (); - - gtk_widget_queue_draw (hslider); - return TRUE; -} - -static void hslider_destroy (GtkWidget * hslider) -{ - g_free (g_object_get_data ((GObject *) hslider, "hsliderdata")); -} - -GtkWidget * hslider_new (int min, int max, SkinPixmapId si, int w, int h, - int fx, int fy, int kw, int kh, int knx, int kny, int kpx, int kpy) -{ - GtkWidget * hslider = gtk_drawing_area_new (); - gtk_widget_set_size_request (hslider, w * config.scale, h * config.scale); - gtk_widget_add_events (hslider, GDK_BUTTON_PRESS_MASK | - GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK); - - DRAW_CONNECT (hslider, hslider_draw); - - g_signal_connect (hslider, "button-press-event", (GCallback) - hslider_button_press, nullptr); - g_signal_connect (hslider, "button-release-event", (GCallback) - hslider_button_release, nullptr); - g_signal_connect (hslider, "motion-notify-event", (GCallback) - hslider_motion_notify, nullptr); - g_signal_connect (hslider, "destroy", (GCallback) hslider_destroy, nullptr); - - HSliderData * data = g_new0 (HSliderData, 1); - data->min = min; - data->max = max; - data->pos = min; - data->si = si; - data->w = w; - data->h = h; - data->fx = fx; - data->fy = fy; - data->kw = kw; - data->kh = kh; - data->knx = knx; - data->kny = kny; - data->kpx = kpx; - data->kpy = kpy; - g_object_set_data ((GObject *) hslider, "hsliderdata", data); - - return hslider; -} - -void hslider_set_frame (GtkWidget * hslider, int fx, int fy) -{ - HSliderData * data = (HSliderData *) g_object_get_data ((GObject *) hslider, "hsliderdata"); - g_return_if_fail (data); - - data->fx = fx; - data->fy = fy; - gtk_widget_queue_draw (hslider); -} - -void hslider_set_knob (GtkWidget * hslider, int knx, int kny, int kpx, int - kpy) -{ - HSliderData * data = (HSliderData *) g_object_get_data ((GObject *) hslider, "hsliderdata"); - g_return_if_fail (data); - - data->knx = knx; - data->kny = kny; - data->kpx = kpx; - data->kpy = kpy; - gtk_widget_queue_draw (hslider); -} - -int hslider_get_pos (GtkWidget * hslider) -{ - HSliderData * data = (HSliderData *) g_object_get_data ((GObject *) hslider, "hsliderdata"); - g_return_val_if_fail (data, 0); - - return data->pos; -} - -void hslider_set_pos (GtkWidget * hslider, int pos) -{ - HSliderData * data = (HSliderData *) g_object_get_data ((GObject *) hslider, "hsliderdata"); - g_return_if_fail (data); - - if (data->pressed) - return; - - data->pos = aud::clamp (pos, data->min, data->max); - gtk_widget_queue_draw (hslider); -} - -gboolean hslider_get_pressed (GtkWidget * hslider) -{ - HSliderData * data = (HSliderData *) g_object_get_data ((GObject *) hslider, "hsliderdata"); - g_return_val_if_fail (data, FALSE); - - return data->pressed; -} - -void hslider_set_pressed (GtkWidget * hslider, gboolean pressed) -{ - HSliderData * data = (HSliderData *) g_object_get_data ((GObject *) hslider, "hsliderdata"); - g_return_if_fail (data); - - data->pressed = pressed; - gtk_widget_queue_draw (hslider); -} - -void hslider_on_motion (GtkWidget * hslider, void (* callback) (void)) -{ - HSliderData * data = (HSliderData *) g_object_get_data ((GObject *) hslider, "hsliderdata"); - g_return_if_fail (data); - - data->on_motion = callback; -} - -void hslider_on_release (GtkWidget * hslider, void (* callback) (void)) -{ - HSliderData * data = (HSliderData *) g_object_get_data ((GObject *) hslider, "hsliderdata"); - g_return_if_fail (data); - - data->on_release = callback; -} diff --git a/src/skins/ui_skinned_number.cc b/src/skins/ui_skinned_number.cc deleted file mode 100644 index 53977cc..0000000 --- a/src/skins/ui_skinned_number.cc +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Audacious - a cross-platform multimedia player - * Copyright (c) 2007 Tomasz Moń - * Copyright (c) 2011 John Lindgren - * - * Based on: - * BMP - Cross-platform multimedia player - * Copyright (C) 2003-2004 BMP development team. - * XMMS: - * Copyright (C) 1998-2003 XMMS development team. - * - * 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; under version 3 of the License. - * - * 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 <http://www.gnu.org/licenses>. - * - * The Audacious team does not consider modular code linking to - * Audacious or using our public API to be a derived work. - */ - -#include "draw-compat.h" -#include "skins_cfg.h" -#include "ui_skin.h" -#include "ui_skinned_number.h" - -typedef struct { - int w, h; - int num; -} NumberData; - -DRAW_FUNC_BEGIN (number_draw) - NumberData * data = (NumberData *) g_object_get_data ((GObject *) wid, "numberdata"); - g_return_val_if_fail (data, FALSE); - - skin_draw_pixbuf (cr, SKIN_NUMBERS, data->num * 9, 0, 0, 0, data->w, data->h); -DRAW_FUNC_END - -static void number_destroy (GtkWidget * number) -{ - g_free (g_object_get_data ((GObject *) number, "numberdata")); -} - -GtkWidget * ui_skinned_number_new (void) -{ - GtkWidget * number = gtk_drawing_area_new (); - gtk_widget_set_size_request (number, 9 * config.scale, 13 * config.scale); - - gtk_widget_add_events (number, GDK_BUTTON_PRESS_MASK | - GDK_BUTTON_RELEASE_MASK); - - DRAW_CONNECT (number, number_draw); - g_signal_connect (number, "destroy", (GCallback) number_destroy, nullptr); - - NumberData * data = g_new0 (NumberData, 1); - data->w = 9; - data->h = 13; - g_object_set_data ((GObject *) number, "numberdata", data); - - return number; -} - -void ui_skinned_number_set (GtkWidget * number, char c) -{ - NumberData * data = (NumberData *) g_object_get_data ((GObject *) number, "numberdata"); - g_return_if_fail (data); - - int value = (c >= '0' && c <= '9') ? c - '0' : (c == '-') ? 11 : 10; - - if (data->num == value) - return; - - data->num = value; - gtk_widget_queue_draw (number); -} - -void ui_skinned_number_set_size (GtkWidget * number, int width, int height) -{ - NumberData * data = (NumberData *) g_object_get_data ((GObject *) number, "numberdata"); - g_return_if_fail (data); - - data->w = width; - data->h = height; - - gtk_widget_set_size_request (number, width * config.scale, height * config.scale); - gtk_widget_queue_draw (number); -} diff --git a/src/skins/ui_skinned_playlist.cc b/src/skins/ui_skinned_playlist.cc deleted file mode 100644 index 3408356..0000000 --- a/src/skins/ui_skinned_playlist.cc +++ /dev/null @@ -1,945 +0,0 @@ -/* - * Audacious - a cross-platform multimedia player - * Copyright (c) 2007 Tomasz Moń - * Copyright (c) 2008 William Pitcock - * Copyright (c) 2009-2011 John Lindgren - * - * Based on: - * BMP - Cross-platform multimedia player - * Copyright (C) 2003-2004 BMP development team. - * - * XMMS: - * Copyright (C) 1998-2003 XMMS development team. - * - * 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; under version 3 of the License. - * - * 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 <http://www.gnu.org/licenses>. - * - * The Audacious team does not consider modular code linking to - * Audacious or using our public API to be a derived work. - */ - -#include <gdk/gdkkeysyms.h> - -#include "draw-compat.h" -#include "menus.h" -#include "skins_cfg.h" -#include "ui_playlist.h" -#include "ui_skin.h" -#include "ui_skinned_playlist.h" -#include "ui_skinned_playlist_slider.h" - -#include <libaudcore/audstrings.h> -#include <libaudcore/runtime.h> -#include <libaudcore/playlist.h> -#include <libaudgui/libaudgui.h> - -enum {DRAG_SELECT = 1, DRAG_MOVE}; - -typedef struct { - GtkWidget * slider; - PangoFontDescription * font; - int width, height, row_height, offset, rows, first, scroll, scroll_source, - hover, drag; - int popup_pos, popup_source; - gboolean popup_shown; -} PlaylistData; - -static gboolean playlist_button_press (GtkWidget * list, GdkEventButton * event); -static gboolean playlist_button_release (GtkWidget * list, GdkEventButton * - event); -static gboolean playlist_motion (GtkWidget * list, GdkEventMotion * event); -static gboolean playlist_leave (GtkWidget * list, GdkEventCrossing * event); - -static void popup_trigger (GtkWidget * list, PlaylistData * data, int pos); -static void popup_hide (GtkWidget * list, PlaylistData * data); - -static void calc_layout (PlaylistData * data) -{ - data->rows = data->height / data->row_height; - - if (data->rows && active_title) - { - data->offset = data->row_height; - data->rows --; - } - else - data->offset = 0; - - if (data->first + data->rows > active_length) - data->first = active_length - data->rows; - if (data->first < 0) - data->first = 0; -} - -static int calc_position (PlaylistData * data, int y) -{ - if (y < data->offset) - return -1; - - int position = data->first + (y - data->offset) / data->row_height; - - if (position >= data->first + data->rows || position >= active_length) - return active_length; - - return position; -} - -static int adjust_position (PlaylistData * data, gboolean relative, int - position) -{ - if (active_length == 0) - return -1; - - if (relative) - { - int focus = aud_playlist_get_focus (active_playlist); - if (focus == -1) - return 0; - - position += focus; - } - - if (position < 0) - return 0; - if (position >= active_length) - return active_length - 1; - - return position; -} - -static void cancel_all (GtkWidget * list, PlaylistData * data) -{ - data->drag = FALSE; - - if (data->scroll) - { - data->scroll = 0; - g_source_remove (data->scroll_source); - } - - if (data->hover != -1) - { - data->hover = -1; - gtk_widget_queue_draw (list); - } - - popup_hide (list, data); -} - -DRAW_FUNC_BEGIN (playlist_draw) - PlaylistData * data = (PlaylistData *) g_object_get_data ((GObject *) wid, "playlistdata"); - g_return_val_if_fail (data, FALSE); - - int active_entry = aud_playlist_get_position (active_playlist); - int left = 3, right = 3; - PangoLayout * layout; - int width; - - /* background */ - - set_cairo_color (cr, active_skin->colors[SKIN_PLEDIT_NORMALBG]); - cairo_paint (cr); - - /* playlist title */ - - if (data->offset) - { - layout = gtk_widget_create_pango_layout (wid, active_title); - pango_layout_set_font_description (layout, data->font); - pango_layout_set_width (layout, PANGO_SCALE * (data->width - left - - right)); - pango_layout_set_alignment (layout, PANGO_ALIGN_CENTER); - pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_MIDDLE); - - cairo_move_to (cr, left, 0); - set_cairo_color (cr, active_skin->colors[SKIN_PLEDIT_NORMAL]); - pango_cairo_show_layout (cr, layout); - g_object_unref (layout); - } - - /* selection highlight */ - - for (int i = data->first; i < data->first + data->rows && i < - active_length; i ++) - { - if (! aud_playlist_entry_get_selected (active_playlist, i)) - continue; - - cairo_rectangle (cr, 0, data->offset + data->row_height * (i - - data->first), data->width, data->row_height); - set_cairo_color (cr, active_skin->colors[SKIN_PLEDIT_SELECTEDBG]); - cairo_fill (cr); - } - - /* entry numbers */ - - if (aud_get_bool (nullptr, "show_numbers_in_pl")) - { - width = 0; - - for (int i = data->first; i < data->first + data->rows && i < - active_length; i ++) - { - char buf[16]; - snprintf (buf, sizeof buf, "%d.", 1 + i); - - layout = gtk_widget_create_pango_layout (wid, buf); - pango_layout_set_font_description (layout, data->font); - - PangoRectangle rect; - pango_layout_get_pixel_extents (layout, nullptr, & rect); - width = aud::max (width, rect.width); - - cairo_move_to (cr, left, data->offset + data->row_height * (i - - data->first)); - set_cairo_color (cr, active_skin->colors[(i == active_entry) ? - SKIN_PLEDIT_CURRENT : SKIN_PLEDIT_NORMAL]); - pango_cairo_show_layout (cr, layout); - g_object_unref (layout); - } - - left += width + 4; - } - - /* entry lengths */ - - width = 0; - - for (int i = data->first; i < data->first + data->rows && i < - active_length; i ++) - { - Tuple tuple = aud_playlist_entry_get_tuple (active_playlist, i, Playlist::Guess); - int len = tuple.get_int (Tuple::Length); - if (len < 0) - continue; - - layout = gtk_widget_create_pango_layout (wid, str_format_time (len)); - pango_layout_set_font_description (layout, data->font); - - PangoRectangle rect; - pango_layout_get_pixel_extents (layout, nullptr, & rect); - width = aud::max (width, rect.width); - - cairo_move_to (cr, data->width - right - rect.width, data->offset + - data->row_height * (i - data->first)); - set_cairo_color (cr, active_skin->colors[(i == active_entry) ? - SKIN_PLEDIT_CURRENT : SKIN_PLEDIT_NORMAL]); - pango_cairo_show_layout (cr, layout); - g_object_unref (layout); - } - - right += width + 6; - - /* queue positions */ - - if (aud_playlist_queue_count (active_playlist)) - { - width = 0; - - for (int i = data->first; i < data->first + data->rows && i < - active_length; i ++) - { - int pos = aud_playlist_queue_find_entry (active_playlist, i); - if (pos < 0) - continue; - - char buf[16]; - snprintf (buf, sizeof buf, "(#%d)", 1 + pos); - - layout = gtk_widget_create_pango_layout (wid, buf); - pango_layout_set_font_description (layout, data->font); - - PangoRectangle rect; - pango_layout_get_pixel_extents (layout, nullptr, & rect); - width = aud::max (width, rect.width); - - cairo_move_to (cr, data->width - right - rect.width, data->offset + - data->row_height * (i - data->first)); - set_cairo_color (cr, active_skin->colors[(i == active_entry) ? - SKIN_PLEDIT_CURRENT : SKIN_PLEDIT_NORMAL]); - pango_cairo_show_layout (cr, layout); - g_object_unref (layout); - } - - right += width + 6; - } - - /* titles */ - - for (int i = data->first; i < data->first + data->rows && i < - active_length; i ++) - { - Tuple tuple = aud_playlist_entry_get_tuple (active_playlist, i, Playlist::Guess); - String title = tuple.get_str (Tuple::FormattedTitle); - - layout = gtk_widget_create_pango_layout (wid, title); - pango_layout_set_font_description (layout, data->font); - pango_layout_set_width (layout, PANGO_SCALE * (data->width - left - - right)); - pango_layout_set_ellipsize (layout, PANGO_ELLIPSIZE_END); - - cairo_move_to (cr, left, data->offset + data->row_height * (i - - data->first)); - set_cairo_color (cr, active_skin->colors[(i == active_entry) ? - SKIN_PLEDIT_CURRENT : SKIN_PLEDIT_NORMAL]); - pango_cairo_show_layout (cr, layout); - g_object_unref (layout); - } - - /* focus rectangle */ - - int focus = aud_playlist_get_focus (active_playlist); - if (focus >= data->first && focus <= data->first + data->rows - 1) - { - cairo_new_path (cr); - cairo_set_line_width (cr, 1); - cairo_rectangle (cr, 0.5, data->offset + data->row_height * (focus - - data->first) + 0.5, data->width - 1, data->row_height - 1); - set_cairo_color (cr, active_skin->colors[SKIN_PLEDIT_NORMAL]); - cairo_stroke (cr); - } - - /* hover line */ - - if (data->hover >= data->first && data->hover <= data->first + data->rows) - { - cairo_new_path (cr); - cairo_set_line_width (cr, 2); - cairo_move_to (cr, 0, data->offset + data->row_height * (data->hover - - data->first)); - cairo_rel_line_to (cr, data->width, 0); - set_cairo_color (cr, active_skin->colors[SKIN_PLEDIT_NORMAL]); - cairo_stroke (cr); - } -DRAW_FUNC_END - -static void playlist_destroy (GtkWidget * list) -{ - PlaylistData * data = (PlaylistData *) g_object_get_data ((GObject *) list, "playlistdata"); - g_return_if_fail (data); - - cancel_all (list, data); - - pango_font_description_free (data->font); - g_free (data); -} - -GtkWidget * ui_skinned_playlist_new (int width, int height, const char * font) -{ - GtkWidget * list = gtk_drawing_area_new (); - gtk_widget_set_size_request (list, width * config.scale, height * config.scale); - gtk_widget_add_events (list, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - | GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK); - - DRAW_CONNECT (list, playlist_draw); - g_signal_connect (list, "button-press-event", (GCallback) - playlist_button_press, nullptr); - g_signal_connect (list, "button-release-event", (GCallback) - playlist_button_release, nullptr); - g_signal_connect (list, "leave-notify-event", (GCallback) playlist_leave, - nullptr); - g_signal_connect (list, "motion-notify-event", (GCallback) playlist_motion, - nullptr); - g_signal_connect (list, "destroy", (GCallback) playlist_destroy, nullptr); - - PlaylistData * data = g_new0 (PlaylistData, 1); - data->width = width * config.scale; - data->height = height * config.scale; - data->hover = -1; - data->popup_pos = -1; - g_object_set_data ((GObject *) list, "playlistdata", data); - - ui_skinned_playlist_set_font (list, font); - - return list; -} - -void ui_skinned_playlist_set_slider (GtkWidget * list, GtkWidget * slider) -{ - PlaylistData * data = (PlaylistData *) g_object_get_data ((GObject *) list, "playlistdata"); - g_return_if_fail (data); - - data->slider = slider; -} - -void ui_skinned_playlist_resize (GtkWidget * list, int width, int height) -{ - PlaylistData * data = (PlaylistData *) g_object_get_data ((GObject *) list, "playlistdata"); - g_return_if_fail (data); - - gtk_widget_set_size_request (list, width * config.scale, height * config.scale); - - data->width = width * config.scale; - data->height = height * config.scale; - - calc_layout (data); - gtk_widget_queue_draw (list); - - if (data->slider) - ui_skinned_playlist_slider_update (data->slider); -} - -void ui_skinned_playlist_set_font (GtkWidget * list, const char * font) -{ - PlaylistData * data = (PlaylistData *) g_object_get_data ((GObject *) list, "playlistdata"); - g_return_if_fail (data); - - pango_font_description_free (data->font); - data->font = pango_font_description_from_string (font); - - PangoLayout * layout = gtk_widget_create_pango_layout (list, "A"); - pango_layout_set_font_description (layout, data->font); - - PangoRectangle rect; - pango_layout_get_pixel_extents (layout, nullptr, & rect); - - /* make sure row_height is non-zero; we divide by it */ - data->row_height = aud::max (rect.height, 1); - - g_object_unref (layout); - - calc_layout (data); - gtk_widget_queue_draw (list); - - if (data->slider) - ui_skinned_playlist_slider_update (data->slider); -} - -void ui_skinned_playlist_update (GtkWidget * list) -{ - PlaylistData * data = (PlaylistData *) g_object_get_data ((GObject *) list, "playlistdata"); - g_return_if_fail (data); - - calc_layout (data); - - gtk_widget_queue_draw (list); - - if (data->slider != nullptr) - ui_skinned_playlist_slider_update (data->slider); -} - -static void scroll_to (PlaylistData * data, int position) -{ - if (position < data->first || position >= data->first + data->rows) - data->first = position - data->rows / 2; - - calc_layout (data); -} - -static void select_single (PlaylistData * data, gboolean relative, int position) -{ - position = adjust_position (data, relative, position); - - if (position == -1) - return; - - aud_playlist_select_all (active_playlist, FALSE); - aud_playlist_entry_set_selected (active_playlist, position, TRUE); - aud_playlist_set_focus (active_playlist, position); - scroll_to (data, position); -} - -static void select_extend (PlaylistData * data, gboolean relative, int position) -{ - position = adjust_position (data, relative, position); - - if (position == -1) - return; - - int count = adjust_position (data, TRUE, 0); - int sign = (position > count) ? 1 : -1; - - for (; count != position; count += sign) - aud_playlist_entry_set_selected (active_playlist, count, - ! aud_playlist_entry_get_selected (active_playlist, count + sign)); - - aud_playlist_entry_set_selected (active_playlist, position, TRUE); - aud_playlist_set_focus (active_playlist, position); - scroll_to (data, position); -} - -static void select_slide (PlaylistData * data, gboolean relative, int position) -{ - position = adjust_position (data, relative, position); - - if (position == -1) - return; - - aud_playlist_set_focus (active_playlist, position); - scroll_to (data, position); -} - -static void select_toggle (PlaylistData * data, gboolean relative, int position) -{ - position = adjust_position (data, relative, position); - - if (position == -1) - return; - - aud_playlist_entry_set_selected (active_playlist, position, - ! aud_playlist_entry_get_selected (active_playlist, position)); - aud_playlist_set_focus (active_playlist, position); - scroll_to (data, position); -} - -static void select_move (PlaylistData * data, gboolean relative, int position) -{ - int focus = aud_playlist_get_focus (active_playlist); - position = adjust_position (data, relative, position); - - if (focus == -1 || position == -1 || position == focus) - return; - - focus += aud_playlist_shift (active_playlist, focus, position - focus); - scroll_to (data, focus); -} - -static void delete_selected (PlaylistData * data) -{ - aud_playlist_delete_selected (active_playlist); - - active_length = aud_playlist_entry_count (active_playlist); - int focus = aud_playlist_get_focus (active_playlist); - - if (focus != -1) - { - aud_playlist_entry_set_selected (active_playlist, focus, TRUE); - scroll_to (data, focus); - } -} - -gboolean ui_skinned_playlist_key (GtkWidget * list, GdkEventKey * event) -{ - PlaylistData * data = (PlaylistData *) g_object_get_data ((GObject *) list, "playlistdata"); - g_return_val_if_fail (data, FALSE); - - cancel_all (list, data); - - switch (event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK)) - { - case 0: - switch (event->keyval) - { - case GDK_KEY_Up: - select_single (data, TRUE, -1); - break; - case GDK_KEY_Down: - select_single (data, TRUE, 1); - break; - case GDK_KEY_Page_Up: - select_single (data, TRUE, - data->rows); - break; - case GDK_KEY_Page_Down: - select_single (data, TRUE, data->rows); - break; - case GDK_KEY_Home: - select_single (data, FALSE, 0); - break; - case GDK_KEY_End: - select_single (data, FALSE, active_length - 1); - break; - case GDK_KEY_Return: - select_single (data, TRUE, 0); - aud_playlist_set_position (active_playlist, - aud_playlist_get_focus (active_playlist)); - aud_playlist_play (active_playlist); - break; - case GDK_KEY_Escape: - select_single (data, FALSE, aud_playlist_get_position - (active_playlist)); - break; - case GDK_KEY_Delete: - delete_selected (data); - break; - default: - return FALSE; - } - break; - case GDK_SHIFT_MASK: - switch (event->keyval) - { - case GDK_KEY_Up: - select_extend (data, TRUE, -1); - break; - case GDK_KEY_Down: - select_extend (data, TRUE, 1); - break; - case GDK_KEY_Page_Up: - select_extend (data, TRUE, -data->rows); - break; - case GDK_KEY_Page_Down: - select_extend (data, TRUE, data->rows); - break; - case GDK_KEY_Home: - select_extend (data, FALSE, 0); - break; - case GDK_KEY_End: - select_extend (data, FALSE, active_length - 1); - break; - default: - return FALSE; - } - break; - case GDK_CONTROL_MASK: - switch (event->keyval) - { - case GDK_KEY_space: - select_toggle (data, TRUE, 0); - break; - case GDK_KEY_Up: - select_slide (data, TRUE, -1); - break; - case GDK_KEY_Down: - select_slide (data, TRUE, 1); - break; - case GDK_KEY_Page_Up: - select_slide (data, TRUE, -data->rows); - break; - case GDK_KEY_Page_Down: - select_slide (data, TRUE, data->rows); - break; - case GDK_KEY_Home: - select_slide (data, FALSE, 0); - break; - case GDK_KEY_End: - select_slide (data, FALSE, active_length - 1); - break; - default: - return FALSE; - } - break; - case GDK_MOD1_MASK: - switch (event->keyval) - { - case GDK_KEY_Up: - select_move (data, TRUE, -1); - break; - case GDK_KEY_Down: - select_move (data, TRUE, 1); - break; - case GDK_KEY_Page_Up: - select_move (data, TRUE, -data->rows); - break; - case GDK_KEY_Page_Down: - select_move (data, TRUE, data->rows); - break; - case GDK_KEY_Home: - select_move (data, FALSE, 0); - break; - case GDK_KEY_End: - select_move (data, FALSE, active_length - 1); - break; - default: - return FALSE; - } - break; - default: - return FALSE; - } - - playlistwin_update (); - return TRUE; -} - -void ui_skinned_playlist_row_info (GtkWidget * list, int * rows, int * first) -{ - PlaylistData * data = (PlaylistData *) g_object_get_data ((GObject *) list, "playlistdata"); - g_return_if_fail (data); - - * rows = data->rows; - * first = data->first; -} - -void ui_skinned_playlist_scroll_to (GtkWidget * list, int row) -{ - PlaylistData * data = (PlaylistData *) g_object_get_data ((GObject *) list, "playlistdata"); - g_return_if_fail (data); - - cancel_all (list, data); - data->first = row; - calc_layout (data); - - gtk_widget_queue_draw (list); - - if (data->slider) - ui_skinned_playlist_slider_update (data->slider); -} - -void ui_skinned_playlist_set_focused (GtkWidget * list, int row) -{ - PlaylistData * data = (PlaylistData *) g_object_get_data ((GObject *) list, "playlistdata"); - g_return_if_fail (data); - - cancel_all (list, data); - aud_playlist_set_focus (active_playlist, row); - scroll_to (data, row); - - gtk_widget_queue_draw (list); -} - -void ui_skinned_playlist_hover (GtkWidget * list, int x, int y) -{ - PlaylistData * data = (PlaylistData *) g_object_get_data ((GObject *) list, "playlistdata"); - g_return_if_fail (data); - - int row; - - if (y < data->offset) - row = data->first; - else if (y > data->offset + data->row_height * data->rows) - row = data->first + data->rows; - else - row = data->first + (y - data->offset + data->row_height / 2) / - data->row_height; - - if (row > active_length) - row = active_length; - - if (row != data->hover) - { - data->hover = row; - gtk_widget_queue_draw (list); - } -} - -int ui_skinned_playlist_hover_end (GtkWidget * list) -{ - PlaylistData * data = (PlaylistData *) g_object_get_data ((GObject *) list, "playlistdata"); - g_return_val_if_fail (data, -1); - - int temp = data->hover; - data->hover = -1; - - gtk_widget_queue_draw (list); - return temp; -} - -static gboolean playlist_button_press (GtkWidget * list, GdkEventButton * event) -{ - PlaylistData * data = (PlaylistData *) g_object_get_data ((GObject *) list, "playlistdata"); - g_return_val_if_fail (data, FALSE); - - int position = calc_position (data, event->y); - int state = event->state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | - GDK_MOD1_MASK); - - cancel_all (list, data); - - switch (event->type) - { - case GDK_BUTTON_PRESS: - switch (event->button) - { - case 1: - if (position == -1 || position == active_length) - return TRUE; - - switch (state) - { - case 0: - if (aud_playlist_entry_get_selected (active_playlist, position)) - select_slide (data, FALSE, position); - else - select_single (data, FALSE, position); - - data->drag = DRAG_MOVE; - break; - case GDK_SHIFT_MASK: - select_extend (data, FALSE, position); - data->drag = DRAG_SELECT; - break; - case GDK_CONTROL_MASK: - select_toggle (data, FALSE, position); - data->drag = DRAG_SELECT; - break; - default: - return TRUE; - } - - break; - case 3: - if (state) - return TRUE; - - if (position != -1 && position != active_length) - { - if (aud_playlist_entry_get_selected (active_playlist, position)) - select_slide (data, FALSE, position); - else - select_single (data, FALSE, position); - } - - menu_popup ((position == -1) ? UI_MENU_PLAYLIST : - UI_MENU_PLAYLIST_CONTEXT, event->x_root, event->y_root, FALSE, - FALSE, 3, event->time); - break; - default: - return FALSE; - } - - break; - case GDK_2BUTTON_PRESS: - if (event->button != 1 || state || position == active_length) - return TRUE; - - if (position != -1) - aud_playlist_set_position (active_playlist, position); - - aud_playlist_play (active_playlist); - break; - default: - return TRUE; - } - - playlistwin_update (); - return TRUE; -} - -static gboolean playlist_button_release (GtkWidget * list, GdkEventButton * - event) -{ - PlaylistData * data = (PlaylistData *) g_object_get_data ((GObject *) list, "playlistdata"); - g_return_val_if_fail (data, FALSE); - - cancel_all (list, data); - return TRUE; -} - -static gboolean scroll_cb (void * data_) -{ - auto data = (PlaylistData *) data_; - int position = adjust_position (data, TRUE, data->scroll); - - if (position == -1) - return G_SOURCE_CONTINUE; - - switch (data->drag) - { - case DRAG_SELECT: - select_extend (data, FALSE, position); - break; - case DRAG_MOVE: - select_move (data, FALSE, position); - break; - } - - playlistwin_update (); - return G_SOURCE_CONTINUE; -} - -static gboolean playlist_motion (GtkWidget * list, GdkEventMotion * event) -{ - PlaylistData * data = (PlaylistData *) g_object_get_data ((GObject *) list, "playlistdata"); - g_return_val_if_fail (data, FALSE); - - int position = calc_position (data, event->y); - int new_scroll; - - if (data->drag) - { - if (position == -1 || position == active_length) - { - new_scroll = (position == -1 ? -1 : 1); - - if (data->scroll != new_scroll) - { - if (data->scroll) - g_source_remove (data->scroll_source); - - data->scroll = new_scroll; - data->scroll_source = g_timeout_add (100, scroll_cb, data); - } - } - else - { - if (data->scroll) - { - data->scroll = 0; - g_source_remove (data->scroll_source); - } - - switch (data->drag) - { - case DRAG_SELECT: - select_extend (data, FALSE, position); - break; - case DRAG_MOVE: - select_move (data, FALSE, position); - break; - } - - playlistwin_update (); - } - } - else - { - if (position == -1 || position == active_length) - cancel_all (list, data); - else if (aud_get_bool (nullptr, "show_filepopup_for_tuple") && data->popup_pos != position) - { - cancel_all (list, data); - popup_trigger (list, data, position); - } - } - - return TRUE; -} - -static gboolean playlist_leave (GtkWidget * list, GdkEventCrossing * event) -{ - PlaylistData * data = (PlaylistData *) g_object_get_data ((GObject *) list, "playlistdata"); - g_return_val_if_fail (data, FALSE); - - if (! data->drag) - cancel_all (list, data); - - return TRUE; -} - -static gboolean popup_show (void * list) -{ - PlaylistData * data = (PlaylistData *) g_object_get_data ((GObject *) list, "playlistdata"); - g_return_val_if_fail (data, FALSE); - - audgui_infopopup_show (active_playlist, data->popup_pos); - data->popup_shown = TRUE; - - g_source_remove (data->popup_source); - data->popup_source = 0; - return G_SOURCE_REMOVE; -} - -static void popup_trigger (GtkWidget * list, PlaylistData * data, int pos) -{ - popup_hide (list, data); - - data->popup_pos = pos; - data->popup_source = g_timeout_add (aud_get_int (nullptr, "filepopup_delay") * - 100, popup_show, list); -} - -static void popup_hide (GtkWidget * list, PlaylistData * data) -{ - if (data->popup_source) - { - g_source_remove (data->popup_source); - data->popup_source = 0; - } - - if (data->popup_shown) - { - audgui_infopopup_hide (); - data->popup_shown = FALSE; - } - - data->popup_pos = -1; -} diff --git a/src/skins/ui_skinned_playlist.h b/src/skins/ui_skinned_playlist.h deleted file mode 100644 index ec91917..0000000 --- a/src/skins/ui_skinned_playlist.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Audacious - a cross-platform multimedia player - * Copyright (c) 2007 Tomasz Moń - * Copyright (c) 2009-2011 John Lindgren - * - * Based on: - * BMP - Cross-platform multimedia player - * Copyright (C) 2003-2004 BMP development team. - * XMMS: - * Copyright (C) 1998-2003 XMMS development team. - * - * 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; under version 3 of the License. - * - * 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 <http://www.gnu.org/licenses>. - * - * The Audacious team does not consider modular code linking to - * Audacious or using our public API to be a derived work. - */ - -#ifndef SKINS_UI_SKINNED_PLAYLIST_H -#define SKINS_UI_SKINNED_PLAYLIST_H - -#include <gtk/gtk.h> - -GtkWidget * ui_skinned_playlist_new (int width, int height, const char * font); -void ui_skinned_playlist_set_slider (GtkWidget * list, GtkWidget * slider); -void ui_skinned_playlist_resize (GtkWidget * list, int w, int h); -void ui_skinned_playlist_set_font (GtkWidget * list, const char * font); -void ui_skinned_playlist_update (GtkWidget * list); -gboolean ui_skinned_playlist_key (GtkWidget * list, GdkEventKey * event); -void ui_skinned_playlist_row_info (GtkWidget * list, int * rows, int * first); -void ui_skinned_playlist_scroll_to (GtkWidget * list, int row); -void ui_skinned_playlist_set_focused (GtkWidget * list, int row); -void ui_skinned_playlist_hover (GtkWidget * list, int x, int y); -int ui_skinned_playlist_hover_end (GtkWidget * list); - -#endif diff --git a/src/skins/ui_skinned_playlist_slider.cc b/src/skins/ui_skinned_playlist_slider.cc deleted file mode 100644 index 19a3cb8..0000000 --- a/src/skins/ui_skinned_playlist_slider.cc +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Audacious - a cross-platform multimedia player - * Copyright (c) 2007 Tomasz Moń - * Copyright (c) 2011 John Lindgren - * - * Based on: - * BMP - Cross-platform multimedia player - * Copyright (C) 2003-2004 BMP development team. - * XMMS: - * Copyright (C) 1998-2003 XMMS development team. - * - * 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; under version 3 of the License. - * - * 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 <http://www.gnu.org/licenses>. - * - * The Audacious team does not consider modular code linking to - * Audacious or using our public API to be a derived work. - */ - -#include <libaudcore/objects.h> - -#include "draw-compat.h" -#include "skins_cfg.h" -#include "ui_playlist.h" -#include "ui_skin.h" -#include "ui_skinned_playlist.h" -#include "ui_skinned_playlist_slider.h" - -static GtkWidget * pl_slider_list; -static int pl_slider_height; -static gboolean pl_slider_pressed; - -DRAW_FUNC_BEGIN (pl_slider_draw) - int rows, first; - ui_skinned_playlist_row_info (pl_slider_list, & rows, & first); - - int range = active_length - rows; - - int y; - if (active_length > rows) - y = (first * (pl_slider_height - 19) + range / 2) / range; - else - y = 0; - - for (int i = 0; i < pl_slider_height / 29; i ++) - skin_draw_pixbuf (cr, SKIN_PLEDIT, 36, 42, 0, 29 * i, 8, 29); - - skin_draw_pixbuf (cr, SKIN_PLEDIT, pl_slider_pressed ? 61 : 52, 53, 0, y, 8, - 18); -DRAW_FUNC_END - -static void pl_slider_set_pos (int y) -{ - y = aud::clamp (y, 0, pl_slider_height - 19); - - int rows, first; - ui_skinned_playlist_row_info (pl_slider_list, & rows, & first); - - int range = pl_slider_height - 19; - - ui_skinned_playlist_scroll_to (pl_slider_list, (y * (active_length - rows) + - range / 2) / range); -} - -static gboolean pl_slider_button_press (GtkWidget * slider, GdkEventButton * - event) -{ - if (event->button != 1) - return FALSE; - - pl_slider_pressed = TRUE; - pl_slider_set_pos (event->y / config.scale - 9); - - gtk_widget_queue_draw (slider); - return TRUE; -} - -static gboolean pl_slider_button_release (GtkWidget * slider, GdkEventButton * - event) -{ - if (event->button != 1) - return FALSE; - - if (! pl_slider_pressed) - return TRUE; - - pl_slider_pressed = FALSE; - pl_slider_set_pos (event->y / config.scale - 9); - - gtk_widget_queue_draw (slider); - return TRUE; -} - -static gboolean pl_slider_motion (GtkWidget * slider, GdkEventMotion * event) -{ - if (! pl_slider_pressed) - return TRUE; - - pl_slider_set_pos (event->y / config.scale - 9); - - gtk_widget_queue_draw (slider); - return TRUE; -} - -GtkWidget * ui_skinned_playlist_slider_new (GtkWidget * list, int height) -{ - GtkWidget * slider = gtk_drawing_area_new (); - gtk_widget_set_size_request (slider, 8 * config.scale, height * config.scale); - gtk_widget_add_events (slider, GDK_BUTTON_PRESS_MASK | - GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK); - - pl_slider_list = list; - pl_slider_height = height; - - DRAW_CONNECT (slider, pl_slider_draw); - g_signal_connect (slider, "button-press-event", (GCallback) - pl_slider_button_press, nullptr); - g_signal_connect (slider, "button-release-event", (GCallback) - pl_slider_button_release, nullptr); - g_signal_connect (slider, "motion-notify-event", (GCallback) - pl_slider_motion, nullptr); - - return slider; -} - -void ui_skinned_playlist_slider_resize (GtkWidget * slider, int height) -{ - pl_slider_height = height; - gtk_widget_set_size_request (slider, 8 * config.scale, height * config.scale); - gtk_widget_queue_draw (slider); -} - -void ui_skinned_playlist_slider_update (GtkWidget * slider) -{ - gtk_widget_queue_draw (slider); -} diff --git a/src/skins/ui_skinned_playstatus.cc b/src/skins/ui_skinned_playstatus.cc deleted file mode 100644 index f4f51e3..0000000 --- a/src/skins/ui_skinned_playstatus.cc +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Audacious - a cross-platform multimedia player - * Copyright (c) 2007 Tomasz Moń - * Copyright (c) 2011 John Lindgren - * - * Based on: - * BMP - Cross-platform multimedia player - * Copyright (C) 2003-2004 BMP development team. - * XMMS: - * Copyright (C) 1998-2003 XMMS development team. - * - * 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; under version 3 of the License. - * - * 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 <http://www.gnu.org/licenses>. - * - * The Audacious team does not consider modular code linking to - * Audacious or using our public API to be a derived work. - */ - -#include "draw-compat.h" -#include "skins_cfg.h" -#include "ui_skin.h" -#include "ui_skinned_playstatus.h" - -static int playstatus_width, playstatus_height; -static PStatus playstatus_status; - -DRAW_FUNC_BEGIN (playstatus_draw) - if (! playstatus_width || ! playstatus_height) - goto DONE; - - if (playstatus_status == STATUS_PLAY) - skin_draw_pixbuf (cr, SKIN_PLAYPAUSE, 36, 0, 0, 0, 3, playstatus_height); - else - skin_draw_pixbuf (cr, SKIN_PLAYPAUSE, 27, 0, 0, 0, 2, playstatus_height); - - switch (playstatus_status) - { - case STATUS_STOP: - skin_draw_pixbuf (cr, SKIN_PLAYPAUSE, 18, 0, 2, 0, 9, playstatus_height); - break; - case STATUS_PAUSE: - skin_draw_pixbuf (cr, SKIN_PLAYPAUSE, 9, 0, 2, 0, 9, playstatus_height); - break; - case STATUS_PLAY: - skin_draw_pixbuf (cr, SKIN_PLAYPAUSE, 1, 0, 3, 0, 8, playstatus_height); - break; - } - -DONE: -DRAW_FUNC_END - -GtkWidget * ui_skinned_playstatus_new (void) -{ - GtkWidget * playstatus = gtk_drawing_area_new (); - DRAW_CONNECT (playstatus, playstatus_draw); - return playstatus; -} - -void ui_skinned_playstatus_set_status (GtkWidget * playstatus, PStatus status) -{ - playstatus_status = status; - gtk_widget_queue_draw (playstatus); -} - -void ui_skinned_playstatus_set_size (GtkWidget * playstatus, int width, int - height) -{ - playstatus_width = width; - playstatus_height = height; - - gtk_widget_set_size_request (playstatus, width * config.scale, height * config.scale); - gtk_widget_queue_draw (playstatus); -} diff --git a/src/skins/ui_skinned_textbox.cc b/src/skins/ui_skinned_textbox.cc deleted file mode 100644 index 574b003..0000000 --- a/src/skins/ui_skinned_textbox.cc +++ /dev/null @@ -1,412 +0,0 @@ -/* - * Audacious - a cross-platform multimedia player - * Copyright (c) 2007 Tomasz Moń - * Copyright (c) 2011 John Lindgren - * - * Based on: - * BMP - Cross-platform multimedia player - * Copyright (C) 2003-2004 BMP development team. - * XMMS: - * Copyright (C) 1998-2003 XMMS development team. - * - * 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; under version 3 of the License. - * - * 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 <http://www.gnu.org/licenses>. - * - * The Audacious team does not consider modular code linking to - * Audacious or using our public API to be a derived work. - */ - -#include <string.h> -#include <libaudcore/objects.h> - -#include "draw-compat.h" -#include "skins_cfg.h" -#include "ui_skin.h" -#include "ui_skinned_textbox.h" - -#define TIMEOUT 30 -#define DELAY 50 - -typedef struct { - int width; - char * text; - PangoFontDescription * font; - cairo_surface_t * buf; - int buf_width; - bool may_scroll, two_way; - bool scrolling, backward; - int scroll_source; - int offset, delay; -} TextboxData; - -static GList * textboxes; - -DRAW_FUNC_BEGIN (textbox_draw) - TextboxData * data = (TextboxData *) g_object_get_data ((GObject *) wid, "textboxdata"); - g_return_val_if_fail (data && data->buf, FALSE); - - if (data->scrolling) - { - cairo_set_source_surface (cr, data->buf, -data->offset * config.scale, 0); - cairo_paint (cr); - - if (-data->offset + data->buf_width < data->width) - { - cairo_set_source_surface (cr, data->buf, (-data->offset + - data->buf_width) * config.scale, 0); - cairo_paint (cr); - } - } - else - { - cairo_set_source_surface (cr, data->buf, 0, 0); - cairo_paint (cr); - } -DRAW_FUNC_END - -static gboolean textbox_scroll (void * textbox) -{ - TextboxData * data = (TextboxData *) g_object_get_data ((GObject *) textbox, "textboxdata"); - g_return_val_if_fail (data, FALSE); - - if (data->delay < DELAY) - { - data->delay ++; - return G_SOURCE_CONTINUE; - } - - if (data->two_way && data->backward) - data->offset --; - else - data->offset ++; - - if (data->two_way && (data->backward ? (data->offset <= 0) : - (data->offset + data->width >= data->buf_width))) - { - data->backward = ! data->backward; - data->delay = 0; - } - - if (! data->two_way && data->offset >= data->buf_width) - data->offset = 0; - - gtk_widget_queue_draw ((GtkWidget *) textbox); - return G_SOURCE_CONTINUE; -} - -static void textbox_render_vector (GtkWidget * textbox, TextboxData * data, - const char * text) -{ - g_return_if_fail (data->font && ! data->buf && text); - - PangoLayout * layout = gtk_widget_create_pango_layout (textbox, text); - pango_layout_set_font_description (layout, data->font); - - PangoRectangle ink, logical; - pango_layout_get_pixel_extents (layout, & ink, & logical); - - /* use logical width so as not to trim off the trailing space of the " --- " */ - /* use ink height since vertical space is quite limited */ - logical.width = aud::max (logical.width, 1); - ink.height = aud::max (ink.height, 1); - - gtk_widget_set_size_request (textbox, data->width * config.scale, ink.height); - - data->buf_width = aud::max ((logical.width + config.scale - 1) / config.scale, data->width); - data->buf = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, - data->buf_width * config.scale, ink.height); - - cairo_t * cr = cairo_create (data->buf); - - set_cairo_color (cr, active_skin->colors[SKIN_TEXTBG]); - cairo_paint (cr); - - cairo_move_to (cr, -logical.x, -ink.y); - set_cairo_color (cr, active_skin->colors[SKIN_TEXTFG]); - pango_cairo_show_layout (cr, layout); - - cairo_destroy (cr); - g_object_unref (layout); -} - -static void lookup_char (const char c, int * x, int * y) -{ - int tx, ty; - - switch (c) - { - case '"': tx = 26; ty = 0; break; - case '@': tx = 27; ty = 0; break; - case ' ': tx = 29; ty = 0; break; - case ':': - case ';': - case '|': tx = 12; ty = 1; break; - case '(': - case '{': tx = 13; ty = 1; break; - case ')': - case '}': tx = 14; ty = 1; break; - case '-': - case '~': tx = 15; ty = 1; break; - case '`': - case '\'': tx = 16; ty = 1; break; - case '!': tx = 17; ty = 1; break; - case '_': tx = 18; ty = 1; break; - case '+': tx = 19; ty = 1; break; - case '\\': tx = 20; ty = 1; break; - case '/': tx = 21; ty = 1; break; - case '[': tx = 22; ty = 1; break; - case ']': tx = 23; ty = 1; break; - case '^': tx = 24; ty = 1; break; - case '&': tx = 25; ty = 1; break; - case '%': tx = 26; ty = 1; break; - case '.': - case ',': tx = 27; ty = 1; break; - case '=': tx = 28; ty = 1; break; - case '$': tx = 29; ty = 1; break; - case '#': tx = 30; ty = 1; break; - case '?': tx = 3; ty = 2; break; - case '*': tx = 4; ty = 2; break; - default: tx = 3; ty = 2; break; /* '?' */ - } - - * x = tx * active_skin->properties.textbox_bitmap_font_width; - * y = ty * active_skin->properties.textbox_bitmap_font_height; -} - -static void textbox_render_bitmap (GtkWidget * textbox, TextboxData * data, - const char * text) -{ - g_return_if_fail (! data->font && ! data->buf && text); - - int cw = active_skin->properties.textbox_bitmap_font_width; - int ch = active_skin->properties.textbox_bitmap_font_height; - - gtk_widget_set_size_request (textbox, data->width * config.scale, ch * config.scale); - - long len; - gunichar * utf32 = g_utf8_to_ucs4 (text, -1, nullptr, & len, nullptr); - g_return_if_fail (utf32); - - data->buf_width = aud::max (cw * (int) len, data->width); - data->buf = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, - data->buf_width * config.scale, ch * config.scale); - - cairo_t * cr = cairo_create (data->buf); - - gunichar * s = utf32; - for (int x = 0; x < data->buf_width; x += cw) - { - gunichar c = * s ? * s ++ : ' '; - int cx = 0, cy = 0; - - if (c >= 'A' && c <= 'Z') - cx = cw * (c - 'A'); - else if (c >= 'a' && c <= 'z') - cx = cw * (c - 'a'); - else if (c >= '0' && c <= '9') - { - cx = cw * (c - '0'); - cy = ch; - } - else - lookup_char (c, & cx, & cy); - - skin_draw_pixbuf (cr, SKIN_TEXT, cx, cy, x, 0, cw, ch); - } - - cairo_destroy (cr); - g_free (utf32); -} - -static void textbox_render (GtkWidget * textbox, TextboxData * data) -{ - g_return_if_fail (data->text); - - if (data->buf) - { - cairo_surface_destroy (data->buf); - data->buf = nullptr; - } - - data->scrolling = FALSE; - data->backward = FALSE; - data->offset = 0; - data->delay = 0; - - if (data->font) - textbox_render_vector (textbox, data, data->text); - else - textbox_render_bitmap (textbox, data, data->text); - - if (data->may_scroll && data->buf_width > data->width) - { - data->scrolling = TRUE; - - if (! data->two_way) - { - if (data->buf) - { - cairo_surface_destroy (data->buf); - data->buf = nullptr; - } - - char * temp = g_strdup_printf ("%s --- ", data->text); - - if (data->font) - textbox_render_vector (textbox, data, temp); - else - textbox_render_bitmap (textbox, data, temp); - - g_free (temp); - } - } - - gtk_widget_queue_draw (textbox); - - if (data->scrolling) - { - if (! data->scroll_source) - data->scroll_source = g_timeout_add (TIMEOUT, textbox_scroll, textbox); - } - else - { - if (data->scroll_source) - { - g_source_remove (data->scroll_source); - data->scroll_source = 0; - } - } -} - -void textbox_set_width (GtkWidget * textbox, int width) -{ - TextboxData * data = (TextboxData *) g_object_get_data ((GObject *) textbox, "textboxdata"); - g_return_if_fail (data); - - if (data->width == width) - return; - - data->width = width; - textbox_render (textbox, data); -} - -const char * textbox_get_text (GtkWidget * textbox) -{ - TextboxData * data = (TextboxData *) g_object_get_data ((GObject *) textbox, "textboxdata"); - g_return_val_if_fail (data, nullptr); - - return data->text; -} - -void textbox_set_text (GtkWidget * textbox, const char * text) -{ - TextboxData * data = (TextboxData *) g_object_get_data ((GObject *) textbox, "textboxdata"); - g_return_if_fail (data); - - if (! text) - text = ""; - - if (data->text && ! strcmp (data->text, text)) - return; - - g_free (data->text); - data->text = g_strdup (text); - textbox_render (textbox, data); -} - -void textbox_set_font (GtkWidget * textbox, const char * font) -{ - TextboxData * data = (TextboxData *) g_object_get_data ((GObject *) textbox, "textboxdata"); - g_return_if_fail (data); - - if (data->font) - { - pango_font_description_free (data->font); - data->font = nullptr; - } - - if (font) - data->font = pango_font_description_from_string (font); - - textbox_render (textbox, data); -} - -void textbox_set_scroll (GtkWidget * textbox, gboolean scroll) -{ - TextboxData * data = (TextboxData *) g_object_get_data ((GObject *) textbox, "textboxdata"); - g_return_if_fail (data); - - if (data->may_scroll == scroll && data->two_way == config.twoway_scroll) - return; - - data->may_scroll = scroll; - data->two_way = config.twoway_scroll; - textbox_render (textbox, data); -} - -static void textbox_destroy (GtkWidget * textbox) -{ - TextboxData * data = (TextboxData *) g_object_get_data ((GObject *) textbox, "textboxdata"); - g_return_if_fail (data); - - if (data->font) - pango_font_description_free (data->font); - if (data->buf) - cairo_surface_destroy (data->buf); - if (data->scroll_source) - g_source_remove (data->scroll_source); - - g_free (data->text); - g_free (data); - - textboxes = g_list_remove (textboxes, textbox); -} - -GtkWidget * textbox_new (int width, const char * text, const char * font, - gboolean scroll) -{ - GtkWidget * textbox = gtk_drawing_area_new (); - gtk_widget_set_size_request (textbox, width, 0); - gtk_widget_add_events (textbox, GDK_BUTTON_PRESS_MASK | - GDK_BUTTON_RELEASE_MASK); - - DRAW_CONNECT (textbox, textbox_draw); - g_signal_connect (textbox, "destroy", (GCallback) textbox_destroy, nullptr); - - TextboxData * data = g_new0 (TextboxData, 1); - data->width = width; - data->text = g_strdup (text); - data->may_scroll = scroll; - data->two_way = config.twoway_scroll; - g_object_set_data ((GObject *) textbox, "textboxdata", data); - - if (font) - data->font = pango_font_description_from_string (font); - - textboxes = g_list_prepend (textboxes, textbox); - - textbox_render (textbox, data); - return textbox; -} - -void textbox_update_all (void) -{ - for (GList * node = textboxes; node; node = node->next) - { - GtkWidget * textbox = (GtkWidget *) node->data; - g_return_if_fail (textbox); - TextboxData * data = (TextboxData *) g_object_get_data ((GObject *) textbox, "textboxdata"); - g_return_if_fail (data); - - textbox_render (textbox, data); - } -} diff --git a/src/skins/ui_skinned_window.cc b/src/skins/ui_skinned_window.cc deleted file mode 100644 index e2875ea..0000000 --- a/src/skins/ui_skinned_window.cc +++ /dev/null @@ -1,246 +0,0 @@ -/* - * ui_skinned_window.c - * Copyright 2011 John Lindgren - * - * This file is part of Audacious. - * - * Audacious 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, version 2 or version 3 of the License. - * - * Audacious 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 - * Audacious. If not, see <http://www.gnu.org/licenses/>. - * - * The Audacious team does not consider modular code linking to Audacious or - * using our public API to be a derived work. - */ - -#include "draw-compat.h" -#include "skins_cfg.h" -#include "ui_dock.h" -#include "ui_skinned_window.h" - -typedef struct { - void (* draw) (GtkWidget * window, cairo_t * cr); - GtkWidget * normal, * shaded; - GdkRegion * shape, * sshape; - gboolean is_shaded, is_moving; -} WindowData; - -DRAW_FUNC_BEGIN (window_draw) - WindowData * data = (WindowData *) g_object_get_data ((GObject *) wid, "windowdata"); - g_return_val_if_fail (data, FALSE); - - if (data->draw) - data->draw (wid, cr); -DRAW_FUNC_END - -static void window_apply_shape (GtkWidget * window) -{ - WindowData * data = (WindowData *) g_object_get_data ((GObject *) window, "windowdata"); - g_return_if_fail (data); - - gdk_window_shape_combine_region (gtk_widget_get_window (window), - data->is_shaded ? data->sshape : data->shape, 0, 0); -} - -static gboolean window_button_press (GtkWidget * window, GdkEventButton * event) -{ - WindowData * data = (WindowData *) g_object_get_data ((GObject *) window, "windowdata"); - g_return_val_if_fail (data, FALSE); - - /* pass double clicks through; they are handled elsewhere */ - if (event->button != 1 || event->type == GDK_2BUTTON_PRESS) - return FALSE; - - if (data->is_moving) - return TRUE; - - dock_move_start (window, event->x_root, event->y_root); - data->is_moving = TRUE; - return TRUE; -} - -static gboolean window_button_release (GtkWidget * window, GdkEventButton * - event) -{ - WindowData * data = (WindowData *) g_object_get_data ((GObject *) window, "windowdata"); - g_return_val_if_fail (data, FALSE); - - if (event->button != 1) - return FALSE; - - data->is_moving = FALSE; - return TRUE; -} - -static gboolean window_motion (GtkWidget * window, GdkEventMotion * event) -{ - WindowData * data = (WindowData *) g_object_get_data ((GObject *) window, "windowdata"); - g_return_val_if_fail (data, FALSE); - - if (! data->is_moving) - return TRUE; - - dock_move (event->x_root, event->y_root); - return TRUE; -} - -static void window_destroy (GtkWidget * window) -{ - WindowData * data = (WindowData *) g_object_get_data ((GObject *) window, "windowdata"); - g_return_if_fail (data); - - dock_remove_window (window); - - if (data->is_shaded) - gtk_container_remove ((GtkContainer *) window, data->shaded); - else - gtk_container_remove ((GtkContainer *) window, data->normal); - - g_object_unref (data->normal); - g_object_unref (data->shaded); - - if (data->shape) - gdk_region_destroy (data->shape); - if (data->sshape) - gdk_region_destroy (data->sshape); - - g_free (data); -} - -GtkWidget * window_new (int * x, int * y, int w, int h, gboolean main, - gboolean shaded, void (* draw) (GtkWidget * window, cairo_t * cr)) -{ - w *= config.scale; - h *= config.scale; - - GtkWidget * window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - gtk_window_set_decorated ((GtkWindow *) window, FALSE); - gtk_window_set_resizable ((GtkWindow *) window, FALSE); - gtk_window_move ((GtkWindow *) window, * x, * y); - gtk_widget_set_size_request (window, w, h); - gtk_window_resize ((GtkWindow *) window, w, h); - - gtk_widget_set_app_paintable (window, TRUE); - gtk_widget_add_events (window, GDK_BUTTON_PRESS_MASK | - GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_SCROLL_MASK); - - DRAW_CONNECT (window, window_draw); - g_signal_connect (window, "realize", (GCallback) window_apply_shape, nullptr); - g_signal_connect (window, "button-press-event", (GCallback) window_button_press, nullptr); - g_signal_connect (window, "button-release-event", (GCallback) window_button_release, nullptr); - g_signal_connect (window, "motion-notify-event", (GCallback) window_motion, nullptr); - g_signal_connect (window, "destroy", (GCallback) window_destroy, nullptr); - - WindowData * data = g_new0 (WindowData, 1); - g_object_set_data ((GObject *) window, "windowdata", data); - - data->normal = gtk_fixed_new (); - g_object_ref (data->normal); - - data->shaded = gtk_fixed_new (); - g_object_ref (data->shaded); - - if (shaded) - gtk_container_add ((GtkContainer *) window, data->shaded); - else - gtk_container_add ((GtkContainer *) window, data->normal); - - data->is_shaded = shaded; - data->draw = draw; - - dock_add_window (window, x, y, w, h, main); - return window; -} - -void window_set_size (GtkWidget * window, int w, int h) -{ - w *= config.scale; - h *= config.scale; - - gtk_widget_set_size_request (window, w, h); - gtk_window_resize ((GtkWindow *) window, w, h); - dock_set_size (window, w, h); -} - -void window_set_shapes (GtkWidget * window, GdkRegion * shape, GdkRegion * sshape) -{ - WindowData * data = (WindowData *) g_object_get_data ((GObject *) window, "windowdata"); - g_return_if_fail (data); - - if (data->shape) - gdk_region_destroy (data->shape); - if (data->sshape) - gdk_region_destroy (data->sshape); - - data->shape = shape; - data->sshape = sshape; - - if (gtk_widget_get_realized (window)) - window_apply_shape (window); -} - -void window_set_shaded (GtkWidget * window, gboolean shaded) -{ - WindowData * data = (WindowData *) g_object_get_data ((GObject *) window, "windowdata"); - g_return_if_fail (data); - - if (data->is_shaded == shaded) - return; - - if (shaded) - { - gtk_container_remove ((GtkContainer *) window, data->normal); - gtk_container_add ((GtkContainer *) window, data->shaded); - } - else - { - gtk_container_remove ((GtkContainer *) window, data->shaded); - gtk_container_add ((GtkContainer *) window, data->normal); - } - - data->is_shaded = shaded; - - if (gtk_widget_get_realized (window)) - window_apply_shape (window); -} - -void window_put_widget (GtkWidget * window, gboolean shaded, GtkWidget * widget, - int x, int y) -{ - x *= config.scale; - y *= config.scale; - - WindowData * data = (WindowData *) g_object_get_data ((GObject *) window, "windowdata"); - g_return_if_fail (data); - - GtkWidget * fixed = shaded ? data->shaded : data->normal; - gtk_fixed_put ((GtkFixed *) fixed, widget, x, y); -} - -void window_move_widget (GtkWidget * window, gboolean shaded, GtkWidget * - widget, int x, int y) -{ - x *= config.scale; - y *= config.scale; - - WindowData * data = (WindowData *) g_object_get_data ((GObject *) window, "windowdata"); - g_return_if_fail (data); - - GtkWidget * fixed = shaded ? data->shaded : data->normal; - gtk_fixed_move ((GtkFixed *) fixed, widget, x, y); -} - -void window_show_all (GtkWidget * window) -{ - WindowData * data = (WindowData *) g_object_get_data ((GObject *) window, "windowdata"); - g_return_if_fail (data); - - gtk_widget_show_all (data->normal); - gtk_widget_show_all (data->shaded); -} diff --git a/src/skins/ui_skinselector.cc b/src/skins/ui_skinselector.cc deleted file mode 100644 index 71b0ae9..0000000 --- a/src/skins/ui_skinselector.cc +++ /dev/null @@ -1,398 +0,0 @@ -/* - * ui_skinselector.c - * Copyright 1998-2003 XMMS Development Team - * Copyright 2003-2004 BMP Development Team - * Copyright 2011 John Lindgren - * - * This file is part of Audacious. - * - * Audacious 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, version 2 or version 3 of the License. - * - * Audacious 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 - * Audacious. If not, see <http://www.gnu.org/licenses/>. - * - * The Audacious team does not consider modular code linking to Audacious or - * using our public API to be a derived work. - */ - -#include <stdlib.h> -#include <string.h> - -#include <libaudcore/i18n.h> -#include <libaudcore/runtime.h> -#include <libaudcore/runtime.h> -#include <libaudgui/libaudgui-gtk.h> - -#include "plugin.h" -#include "ui_skin.h" -#include "ui_skinselector.h" -#include "util.h" - -#define EXTENSION_TARGETS 7 - -static const char *ext_targets[EXTENSION_TARGETS] = { "bmp", "xpm", "png", "svg", - "gif", "jpg", "jpeg" }; - -enum SkinViewCols { - SKIN_VIEW_COL_PREVIEW, - SKIN_VIEW_COL_FORMATTEDNAME, - SKIN_VIEW_COL_NAME, - SKIN_VIEW_N_COLS -}; - -typedef struct { - char *name; - char *desc; - char *path; - GTime *time; -} SkinNode; - -static void skin_view_on_cursor_changed (GtkTreeView * treeview, void * data); - -static GList *skinlist = nullptr; - -static char * -get_thumbnail_filename(const char * path) -{ - char *basename, *pngname, *thumbname; - - g_return_val_if_fail(path != nullptr, nullptr); - - basename = g_path_get_basename(path); - pngname = g_strconcat(basename, ".png", nullptr); - - thumbname = g_build_filename(skins_paths[SKINS_PATH_SKIN_THUMB_DIR], - pngname, nullptr); - - g_free(basename); - g_free(pngname); - - return thumbname; -} - - -static GdkPixbuf * -skin_get_preview(const char * path) -{ - GdkPixbuf *preview = nullptr; - char *dec_path, *preview_path; - gboolean is_archive = FALSE; - int i = 0; - char buf[60]; /* gives us lots of room */ - - if (file_is_archive(path)) - { - if (!(dec_path = archive_decompress(path))) - return nullptr; - - is_archive = TRUE; - } - else - { - dec_path = g_strdup(path); - } - - for (i = 0; i < EXTENSION_TARGETS; i++) - { - sprintf(buf, "main.%s", ext_targets[i]); - - if ((preview_path = find_file_case_path (dec_path, buf)) != nullptr) - break; - } - - if (preview_path) - { - preview = gdk_pixbuf_new_from_file(preview_path, nullptr); - g_free(preview_path); - } - - if (is_archive) - del_directory(dec_path); - - g_free(dec_path); - - return preview; -} - -static GdkPixbuf * skin_get_thumbnail (const char * path) -{ - char * thumbname = get_thumbnail_filename (path); - GdkPixbuf * thumb = nullptr; - - if (g_file_test (thumbname, G_FILE_TEST_EXISTS)) - { - thumb = gdk_pixbuf_new_from_file (thumbname, nullptr); - if (thumb) - goto DONE; - } - - thumb = skin_get_preview (path); - if (! thumb) - goto DONE; - - audgui_pixbuf_scale_within (& thumb, 128); - - if (thumb) - { - make_directory (skins_paths[SKINS_PATH_SKIN_THUMB_DIR]); - gdk_pixbuf_save (thumb, thumbname, "png", nullptr, nullptr); - } - -DONE: - g_free (thumbname); - return thumb; -} - -static void -skinlist_add(const char * filename) -{ - SkinNode *node; - char *basename; - - g_return_if_fail(filename != nullptr); - - node = g_slice_new0(SkinNode); - node->path = g_strdup(filename); - - basename = g_path_get_basename(filename); - - if (file_is_archive(filename)) { - node->name = archive_basename(basename); - node->desc = _("Archived Winamp 2.x skin"); - g_free(basename); - } - else { - node->name = basename; - node->desc = _("Unarchived Winamp 2.x skin"); - } - - skinlist = g_list_prepend(skinlist, node); -} - -static gboolean -scan_skindir_func(const char * path, const char * basename, void * data) -{ - if (g_file_test(path, G_FILE_TEST_IS_REGULAR)) { - if (file_is_archive(path)) { - skinlist_add(path); - } - } - else if (g_file_test(path, G_FILE_TEST_IS_DIR)) { - skinlist_add(path); - } - - return FALSE; -} - -static void -scan_skindir(const char * path) -{ - GError *error = nullptr; - - g_return_if_fail(path != nullptr); - - if (path[0] == '.') - return; - - if (!dir_foreach(path, scan_skindir_func, nullptr, &error)) { - g_warning("Failed to open directory (%s): %s", path, error->message); - g_error_free(error); - return; - } -} - -static int skinlist_compare_func (const void * _a, const void * _b) -{ - const SkinNode * a = (SkinNode *) _a, * b = (SkinNode *) _b; - g_return_val_if_fail (a && a->name, 1); - g_return_val_if_fail (b && b->name, 1); - return g_ascii_strcasecmp (a->name, b->name); -} - -static void skin_free_func (void * _data) -{ - SkinNode * data = (SkinNode *) _data; - g_return_if_fail(data != nullptr); - g_free (data->name); - g_free (data->path); - g_slice_free(SkinNode, data); -} - - -static void -skinlist_clear(void) -{ - if (!skinlist) - return; - - g_list_foreach(skinlist, (GFunc) skin_free_func, nullptr); - g_list_free(skinlist); - skinlist = nullptr; -} - -static void -skinlist_update(void) -{ - char *skinsdir; - - skinlist_clear(); - - if (g_file_test (skins_paths[SKINS_PATH_USER_SKIN_DIR], G_FILE_TEST_EXISTS)) - scan_skindir (skins_paths[SKINS_PATH_USER_SKIN_DIR]); - - char * path = g_strdup_printf ("%s/Skins", aud_get_path (AudPath::DataDir)); - scan_skindir (path); - g_free (path); - - skinsdir = getenv("SKINSDIR"); - if (skinsdir) { - char **dir_list = g_strsplit(skinsdir, ":", 0); - char **dir; - - for (dir = dir_list; *dir; dir++) - scan_skindir(*dir); - g_strfreev(dir_list); - } - - skinlist = g_list_sort(skinlist, skinlist_compare_func); - - g_assert(skinlist != nullptr); -} - -void skin_view_update (GtkTreeView * treeview) -{ - GtkTreeSelection *selection = nullptr; - GtkListStore *store; - GtkTreeIter iter, iter_current_skin; - gboolean have_current_skin = FALSE; - GtkTreePath *path; - - GdkPixbuf *thumbnail; - char *formattedname; - char *name; - GList *entry; - - g_signal_handlers_block_by_func (treeview, (void *) skin_view_on_cursor_changed, nullptr); - - store = GTK_LIST_STORE(gtk_tree_view_get_model(treeview)); - - gtk_list_store_clear(store); - - skinlist_update(); - - for (entry = skinlist; entry; entry = entry->next) - { - SkinNode * node = (SkinNode *) entry->data; - - thumbnail = skin_get_thumbnail (node->path); - formattedname = g_strdup_printf ("<big><b>%s</b></big>\n<i>%s</i>", - node->name, node->desc); - name = node->name; - - gtk_list_store_append(store, &iter); - gtk_list_store_set(store, &iter, - SKIN_VIEW_COL_PREVIEW, thumbnail, - SKIN_VIEW_COL_FORMATTEDNAME, formattedname, - SKIN_VIEW_COL_NAME, name, -1); - if (thumbnail) - g_object_unref(thumbnail); - g_free(formattedname); - - if (g_strstr_len(active_skin->path, - strlen(active_skin->path), name) ) { - iter_current_skin = iter; - have_current_skin = TRUE; - } - } - - if (have_current_skin) { - selection = gtk_tree_view_get_selection(treeview); - gtk_tree_selection_select_iter(selection, &iter_current_skin); - - path = gtk_tree_model_get_path(GTK_TREE_MODEL(store), - &iter_current_skin); - gtk_tree_view_scroll_to_cell(treeview, path, nullptr, TRUE, 0.5, 0.5); - gtk_tree_path_free(path); - } - - g_signal_handlers_unblock_by_func (treeview, (void *) skin_view_on_cursor_changed, nullptr); -} - - -static void -skin_view_on_cursor_changed(GtkTreeView * treeview, - void * data) -{ - GtkTreeModel *model; - GtkTreeSelection *selection; - GtkTreeIter iter; - - GList *node; - char *name; - char *comp = nullptr; - - selection = gtk_tree_view_get_selection(treeview); - - if (!gtk_tree_selection_get_selected(selection, &model, &iter)) - return; - - gtk_tree_model_get(model, &iter, SKIN_VIEW_COL_NAME, &name, -1); - - for (node = skinlist; node; node = g_list_next(node)) { - comp = ((SkinNode *) node->data)->path; - if (g_strrstr(comp, name)) - break; - } - - g_free(name); - - active_skin_load (comp); -} - - -void -skin_view_realize(GtkTreeView * treeview) -{ - GtkListStore *store; - GtkTreeViewColumn *column; - GtkCellRenderer *renderer; - GtkTreeSelection *selection; - - gtk_widget_show_all(GTK_WIDGET(treeview)); - - gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(treeview), TRUE); - gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), FALSE); - - store = gtk_list_store_new(SKIN_VIEW_N_COLS, GDK_TYPE_PIXBUF, - G_TYPE_STRING , G_TYPE_STRING); - gtk_tree_view_set_model(treeview, GTK_TREE_MODEL(store)); - g_object_unref (store); - - column = gtk_tree_view_column_new(); - gtk_tree_view_column_set_sizing(column, GTK_TREE_VIEW_COLUMN_AUTOSIZE); - gtk_tree_view_column_set_spacing(column, 16); - gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), - GTK_TREE_VIEW_COLUMN(column)); - - renderer = gtk_cell_renderer_pixbuf_new(); - gtk_tree_view_column_pack_start(column, renderer, FALSE); - gtk_tree_view_column_set_attributes(column, renderer, "pixbuf", - SKIN_VIEW_COL_PREVIEW, nullptr); - - renderer = gtk_cell_renderer_text_new(); - gtk_tree_view_column_pack_start(column, renderer, TRUE); - gtk_tree_view_column_set_attributes(column, renderer, "markup", - SKIN_VIEW_COL_FORMATTEDNAME, nullptr); - - selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview)); - gtk_tree_selection_set_mode(selection, GTK_SELECTION_BROWSE); - - g_signal_connect(treeview, "cursor-changed", - G_CALLBACK(skin_view_on_cursor_changed), nullptr); -} diff --git a/src/skins/util.cc b/src/skins/util.cc index e93cdee..8c7badc 100644 --- a/src/skins/util.cc +++ b/src/skins/util.cc @@ -31,10 +31,11 @@ #include <glib/gstdio.h> -#include <libaudcore/runtime.h> -#include <libaudcore/i18n.h> #include <libaudcore/audstrings.h> +#include <libaudcore/i18n.h> #include <libaudcore/hook.h> +#include <libaudcore/multihash.h> +#include <libaudcore/runtime.h> #include <libaudcore/vfs.h> #include "util.h" @@ -45,67 +46,66 @@ #define DIRMODE (S_IRWXU) #endif -char * find_file_case (const char * folder, const char * basename) +StringBuf find_file_case_path (const char * folder, const char * basename) { - static GHashTable * cache = nullptr; - GList * list = nullptr; - void * vlist; + static SimpleHash<String, Index<String>> cache; - if (cache == nullptr) - cache = g_hash_table_new ((GHashFunc) str_calc_hash, g_str_equal); + String key (folder); + Index<String> * list = cache.lookup (key); - if (g_hash_table_lookup_extended (cache, folder, nullptr, & vlist)) - list = (GList *) vlist; - else + if (! list) { GDir * handle = g_dir_open (folder, 0, nullptr); if (! handle) - return nullptr; + return StringBuf (); + + list = cache.add (key, Index<String> ()); const char * name; while ((name = g_dir_read_name (handle))) - list = g_list_prepend (list, g_strdup (name)); + list->append (name); - g_hash_table_insert (cache, g_strdup (folder), list); g_dir_close (handle); } - for (; list != nullptr; list = list->next) + for (const String & entry : * list) { - if (! g_ascii_strcasecmp ((char *) list->data, basename)) - return g_strdup ((char *) list->data); + if (! strcmp_nocase (entry, basename)) + return filename_build ({folder, entry}); } - return nullptr; -} - -char * find_file_case_path (const char * folder, const char * basename) -{ - char * found, * path; - - if ((found = find_file_case (folder, basename)) == nullptr) - return nullptr; - - path = g_strdup_printf ("%s/%s", folder, found); - g_free (found); - return path; + return StringBuf (); } VFSFile open_local_file_nocase (const char * folder, const char * basename) { - char * path = find_file_case_path (folder, basename); + StringBuf path = find_file_case_path (folder, basename); if (! path) return VFSFile (); StringBuf uri = filename_to_uri (path); - g_free (path); - if (! uri) return VFSFile (); return VFSFile (uri, "r"); } +StringBuf skin_pixmap_locate (const char * folder, const char * basename, const char * altname) +{ + static const char * const exts[] = {".bmp", ".png", ".xpm"}; + + for (const char * ext : exts) + { + StringBuf name = str_concat({basename, ext}); + name.steal (find_file_case_path (folder, name)); + + if (name) + return name; + } + + return altname ? skin_pixmap_locate (folder, altname) : StringBuf (); +} + char * text_parse_line (char * text) { char * newline = strchr (text, '\n'); @@ -117,23 +117,20 @@ char * text_parse_line (char * text) return newline + 1; } -typedef enum -{ +enum ArchiveType { ARCHIVE_UNKNOWN = 0, - ARCHIVE_DIR, ARCHIVE_TAR, ARCHIVE_TGZ, ARCHIVE_ZIP, ARCHIVE_TBZ2 -} ArchiveType; +}; -typedef char *(*ArchiveExtractFunc) (const char *, const char *); +typedef StringBuf (* ArchiveExtractFunc) (const char *, const char *); -typedef struct -{ +struct ArchiveExtensionType { ArchiveType type; const char *ext; -} ArchiveExtensionType; +}; static ArchiveExtensionType archive_extensions[] = { {ARCHIVE_TAR, ".tar"}, @@ -142,291 +139,218 @@ static ArchiveExtensionType archive_extensions[] = { {ARCHIVE_TGZ, ".tar.gz"}, {ARCHIVE_TGZ, ".tgz"}, {ARCHIVE_TBZ2, ".tar.bz2"}, - {ARCHIVE_TBZ2, ".bz2"}, - {ARCHIVE_UNKNOWN, nullptr} + {ARCHIVE_TBZ2, ".bz2"} }; -static char *archive_extract_tar(const char *archive, const char *dest); -static char *archive_extract_zip(const char *archive, const char *dest); -static char *archive_extract_tgz(const char *archive, const char *dest); -static char *archive_extract_tbz2(const char *archive, const char *dest); +static StringBuf archive_extract_tar (const char * archive, const char * dest); +static StringBuf archive_extract_zip (const char * archive, const char * dest); +static StringBuf archive_extract_tgz (const char * archive, const char * dest); +static StringBuf archive_extract_tbz2 (const char * archive, const char * dest); static ArchiveExtractFunc archive_extract_funcs[] = { nullptr, - nullptr, archive_extract_tar, archive_extract_tgz, archive_extract_zip, archive_extract_tbz2 }; - /* FIXME: these functions can be generalised into a function using a * command lookup table */ -static const char *get_tar_command(void) +static const char * get_tar_command () { - static const char *command = nullptr; + static const char * command = nullptr; - if (!command) + if (! command) { - if (!(command = getenv("TARCMD"))) + if (! (command = getenv("TARCMD"))) command = "tar"; } return command; } -static const char *get_unzip_command(void) +static const char * get_unzip_command () { - static const char *command = nullptr; + static const char * command = nullptr; - if (!command) + if (! command) { - if (!(command = getenv("UNZIPCMD"))) + if (! (command = getenv("UNZIPCMD"))) command = "unzip"; } return command; } - -static char *archive_extract_tar(const char *archive, const char *dest) +static StringBuf archive_extract_tar (const char * archive, const char * dest) { - return g_strdup_printf("%s >/dev/null xf \"%s\" -C %s", get_tar_command(), - archive, dest); + return str_printf ("%s >/dev/null xf \"%s\" -C %s", get_tar_command (), archive, dest); } -static char *archive_extract_zip(const char *archive, const char *dest) +static StringBuf archive_extract_zip (const char * archive, const char * dest) { - return g_strdup_printf("%s >/dev/null -o -j \"%s\" -d %s", - get_unzip_command(), archive, dest); + return str_printf ("%s >/dev/null -o -j \"%s\" -d %s", get_unzip_command (), archive, dest); } -static char *archive_extract_tgz(const char *archive, const char *dest) +static StringBuf archive_extract_tgz (const char * archive, const char * dest) { - return g_strdup_printf("%s >/dev/null xzf \"%s\" -C %s", get_tar_command(), - archive, dest); + return str_printf ("%s >/dev/null xzf \"%s\" -C %s", get_tar_command (), archive, dest); } -static char *archive_extract_tbz2(const char *archive, const char *dest) +static StringBuf archive_extract_tbz2 (const char * archive, const char * dest) { - return g_strdup_printf("bzip2 -dc \"%s\" | %s >/dev/null xf - -C %s", - archive, get_tar_command(), dest); + return str_printf ("bzip2 -dc \"%s\" | %s >/dev/null xf - -C %s", archive, + get_tar_command (), dest); } - -static ArchiveType archive_get_type(const char *filename) +static ArchiveType archive_get_type (const char * filename) { - int i = 0; - - if (g_file_test(filename, G_FILE_TEST_IS_DIR)) - return ARCHIVE_DIR; - - while (archive_extensions[i].ext) + for (auto & ext : archive_extensions) { - if (g_str_has_suffix(filename, archive_extensions[i].ext)) - { - return archive_extensions[i].type; - } - i++; + if (str_has_suffix_nocase (filename, ext.ext)) + return ext.type; } return ARCHIVE_UNKNOWN; } -gboolean file_is_archive(const char *filename) +bool file_is_archive (const char * filename) { - return (archive_get_type(filename) > ARCHIVE_DIR); + return (archive_get_type (filename) != ARCHIVE_UNKNOWN); } -char *archive_basename(const char *str) +StringBuf archive_basename (const char * str) { - int i = 0; - - while (archive_extensions[i].ext) + for (auto & ext : archive_extensions) { - if (str_has_suffix_nocase(str, archive_extensions[i].ext)) - { - const char *end = g_strrstr(str, archive_extensions[i].ext); - if (end) - { - return g_strndup(str, end - str); - } - break; - } - i++; + if (str_has_suffix_nocase (str, ext.ext)) + return str_copy (str, strlen (str) - strlen (ext.ext)); } - return nullptr; + return StringBuf (); } /** * Escapes characters that are special to the shell inside double quotes. * * @param string String to be escaped. - * @return Given string with special characters escaped. Must be freed with g_free(). + * @return Given string with special characters escaped. */ -static char * -escape_shell_chars(const char * string) +static StringBuf escape_shell_chars (const char * string) { const char *special = "$`\"\\"; /* Characters to escape */ - const char *in = string; - char *out, *escaped; - int num = 0; - while (*in != '\0') - if (strchr(special, *in++)) - num++; - - escaped = g_new (char, strlen(string) + num + 1); + int num = 0; + for (const char * in = string; * in; in ++) + { + if (strchr (special, * in)) + num ++; + } - in = string; - out = escaped; + StringBuf escaped (strlen (string) + num); - while (*in != '\0') { - if (strchr(special, *in)) - *out++ = '\\'; - *out++ = *in++; + char * out = escaped; + for (const char * in = string; * in; in ++) + { + if (strchr (special, * in)) + * out ++ = '\\'; + * out ++ = * in; } - *out = '\0'; return escaped; } -/* - decompress_archive - - Decompresses the archive "filename" to a temporary directory, - returns the path to the temp dir, or nullptr if failed, - watch out tho, doesn't actually check if the system command succeeds :-| -*/ - -char *archive_decompress(const char *filename) +/** + * Decompresses the archive "filename" to a temporary directory, + * returns the path to the temp dir, or nullptr if failed + */ +StringBuf archive_decompress (const char * filename) { - char *tmpdir, *cmd, *escaped_filename; - ArchiveType type; - - if ((type = archive_get_type(filename)) <= ARCHIVE_DIR) - return nullptr; - - tmpdir = g_build_filename(g_get_tmp_dir(), "audacious.XXXXXX", nullptr); - if (!g_mkdtemp(tmpdir)) - { - g_free(tmpdir); - AUDDBG("Unable to load skin: Failed to create temporary " - "directory: %s\n", g_strerror(errno)); - return nullptr; - } - - escaped_filename = escape_shell_chars(filename); - cmd = archive_extract_funcs[type] (escaped_filename, tmpdir); - g_free(escaped_filename); + ArchiveType type = archive_get_type (filename); + if (type == ARCHIVE_UNKNOWN) + return StringBuf (); - if (!cmd) + StringBuf tmpdir = filename_build ({g_get_tmp_dir (), "audacious.XXXXXX"}); + if (! g_mkdtemp (tmpdir)) { - AUDDBG("extraction function is nullptr!\n"); - g_free(tmpdir); - return nullptr; + AUDWARN ("Error creating %s: %s\n", strerror (errno)); + return StringBuf (); } - AUDDBG("Attempt to execute \"%s\"\n", cmd); + StringBuf escaped_filename = escape_shell_chars (filename); + StringBuf cmd = archive_extract_funcs[type] (escaped_filename, tmpdir); - if (system(cmd) != 0) + AUDDBG ("Executing \"%s\"\n", (const char *) cmd); + int ret = system (cmd); + if (ret != 0) { - AUDDBG("could not execute cmd %s\n", cmd); - g_free(cmd); - return nullptr; + AUDDBG ("Command \"%s\" returned error %d\n", (const char *) cmd, ret); + return StringBuf (); } - g_free(cmd); return tmpdir; } -static gboolean del_directory_func(const char *path, const char *basename, - void *params) +static void del_directory_func (const char * path, const char *) { - if (!strcmp(basename, ".") || !strcmp(path, "..")) - return FALSE; - - if (g_file_test(path, G_FILE_TEST_IS_DIR)) - { - dir_foreach(path, del_directory_func, nullptr, nullptr); - g_rmdir(path); - return FALSE; - } - - g_unlink(path); - - return FALSE; + if (g_file_test (path, G_FILE_TEST_IS_DIR)) + del_directory (path); + else + g_unlink (path); } -void del_directory(const char *path) +void del_directory (const char * path) { - dir_foreach(path, del_directory_func, nullptr, nullptr); - g_rmdir(path); + dir_foreach (path, del_directory_func); + g_rmdir (path); } -GArray *string_to_garray(const char *str) +Index<int> string_to_int_array (const char * str) { - GArray *array; + Index<int> array; int temp; - const char *ptr = str; - char *endptr; + const char * ptr = str; + char * endptr; - array = g_array_new(FALSE, TRUE, sizeof(int)); for (;;) { - temp = strtol(ptr, &endptr, 10); + temp = strtol (ptr, &endptr, 10); if (ptr == endptr) break; - g_array_append_val(array, temp); + array.append (temp); ptr = endptr; - while (!g_ascii_isdigit((int)*ptr) && (*ptr) != '\0') - ptr++; - if (*ptr == '\0') + while (! g_ascii_isdigit ((int) * ptr) && (* ptr) != '\0') + ptr ++; + if (* ptr == '\0') break; } - return (array); + + return array; } -gboolean dir_foreach(const char *path, DirForeachFunc function, - void * user_data, GError **error) +bool dir_foreach (const char * path, DirForeachFunc func) { - GError *error_out = nullptr; - GDir *dir; - const char *entry; - char *entry_fullpath; - - if (!(dir = g_dir_open(path, 0, &error_out))) - { - g_propagate_error(error, error_out); - return FALSE; - } - - while ((entry = g_dir_read_name(dir))) + GError * error = nullptr; + GDir * dir = g_dir_open (path, 0, & error); + if (! dir) { - entry_fullpath = g_build_filename(path, entry, nullptr); - - if ((*function) (entry_fullpath, entry, user_data)) - { - g_free(entry_fullpath); - break; - } - - g_free(entry_fullpath); + AUDWARN ("Error reading %s: %s\n", path, error->message); + g_error_free (error); + return false; } - g_dir_close(dir); + const char * entry; + while ((entry = g_dir_read_name (dir))) + func (filename_build ({path, entry}), entry); - return TRUE; + g_dir_close (dir); + return true; } -void make_directory(const char *path) +void make_directory (const char * path) { - if (g_mkdir_with_parents(path, DIRMODE) == 0) - return; - - g_printerr(_("Could not create directory (%s): %s\n"), path, - g_strerror(errno)); + if (g_mkdir_with_parents (path, DIRMODE) != 0) + AUDWARN ("Error creating %s: %s\n", strerror (errno)); } diff --git a/src/skins/util.h b/src/skins/util.h index 6c041ae..8a651ed 100644 --- a/src/skins/util.h +++ b/src/skins/util.h @@ -26,30 +26,27 @@ #ifndef UTIL_H #define UTIL_H -#include <glib.h> - #include <libaudcore/vfs.h> -typedef gboolean(*DirForeachFunc) (const char *path, const char *basename, - void * user_data); +typedef void (* DirForeachFunc) (const char * path, const char * basename); -char * find_file_case (const char * folder, const char * basename); -char * find_file_case_path (const char * folder, const char * basename); +StringBuf find_file_case_path (const char * folder, const char * basename); VFSFile open_local_file_nocase (const char * folder, const char * basename); +StringBuf skin_pixmap_locate (const char * folder, const char * basename, + const char * altname = nullptr); char * text_parse_line (char * text); -void make_directory(const char *path); -void del_directory(const char *path); +void make_directory (const char * path); +void del_directory (const char * path); -gboolean dir_foreach(const char *path, DirForeachFunc function, - void * user_data, GError **error); +bool dir_foreach (const char * path, DirForeachFunc func); -GArray *string_to_garray(const char *str); +Index<int> string_to_int_array (const char *str); -gboolean file_is_archive(const char *filename); -char *archive_decompress(const char *path); -char *archive_basename(const char *path); +bool file_is_archive (const char * filename); +StringBuf archive_basename (const char * str); +StringBuf archive_decompress (const char * path); #endif diff --git a/src/skins/view.cc b/src/skins/view.cc index 8baac93..b48598c 100644 --- a/src/skins/view.cc +++ b/src/skins/view.cc @@ -1,6 +1,6 @@ /* * view.c - * Copyright 2014 John Lindgren + * Copyright 2014-2015 John Lindgren * * This file is part of Audacious. * @@ -21,37 +21,41 @@ #include "view.h" -#include <libaudcore/runtime.h> #include <libaudcore/hook.h> +#include <libaudcore/mainloop.h> +#include <libaudcore/runtime.h> #include "plugin.h" #include "plugin-window.h" #include "skins_cfg.h" -#include "ui_equalizer.h" -#include "ui_main.h" -#include "ui_main_evlisteners.h" -#include "ui_playlist.h" -#include "ui_skinned_button.h" -#include "ui_skinned_menurow.h" -#include "ui_skinned_window.h" +#include "equalizer.h" +#include "main.h" +#include "vis-callbacks.h" +#include "playlist.h" +#include "button.h" +#include "eq-graph.h" +#include "textbox.h" +#include "menurow.h" +#include "window.h" +#include "vis.h" void view_show_player (bool show) { if (show) { - gtk_window_present ((GtkWindow *) mainwin); + gtk_window_present ((GtkWindow *) mainwin->gtk ()); show_plugin_windows (); } else { - gtk_widget_hide (mainwin); + mainwin->hide (); hide_plugin_windows (); } view_apply_show_playlist (); view_apply_show_equalizer (); - start_stop_visual (FALSE); + start_stop_visual (false); } void view_set_show_playlist (bool show) @@ -62,16 +66,22 @@ void view_set_show_playlist (bool show) view_apply_show_playlist (); } -void view_apply_show_playlist (void) +void view_apply_show_playlist () { bool show = aud_get_bool ("skins", "playlist_visible"); - if (show && gtk_widget_get_visible (mainwin)) - gtk_window_present ((GtkWindow *) playlistwin); + GtkWidget * main = mainwin->gtk (); + GtkWidget * pl = playlistwin->gtk (); + + if (show && gtk_widget_get_visible (main)) + { + gtk_window_set_transient_for ((GtkWindow *) pl, (GtkWindow *) main); + gtk_window_present ((GtkWindow *) pl); + } else - gtk_widget_hide (playlistwin); + playlistwin->hide (); - button_set_active (mainwin_pl, show); + mainwin_pl->set_active (show); } void view_set_show_equalizer (bool show) @@ -82,16 +92,22 @@ void view_set_show_equalizer (bool show) view_apply_show_equalizer (); } -void view_apply_show_equalizer (void) +void view_apply_show_equalizer () { bool show = aud_get_bool ("skins", "equalizer_visible"); - if (show && gtk_widget_get_visible (mainwin)) - gtk_window_present ((GtkWindow *) equalizerwin); + GtkWidget * main = mainwin->gtk (); + GtkWidget * eq = equalizerwin->gtk (); + + if (show && gtk_widget_get_visible (main)) + { + gtk_window_set_transient_for ((GtkWindow *) eq, (GtkWindow *) main); + gtk_window_present ((GtkWindow *) eq); + } else - gtk_widget_hide (equalizerwin); + equalizerwin->hide (); - button_set_active (mainwin_eq, show); + mainwin_eq->set_active (show); } void view_set_player_shaded (bool shaded) @@ -102,15 +118,18 @@ void view_set_player_shaded (bool shaded) view_apply_player_shaded (); } -void view_apply_player_shaded (void) +void view_apply_player_shaded () { bool shaded = aud_get_bool ("skins", "player_shaded"); - window_set_shaded (mainwin, shaded); + mainwin->set_shaded (shaded); + + int width = shaded ? MAINWIN_SHADED_WIDTH : skin.hints.mainwin_width; + int height = shaded ? MAINWIN_SHADED_HEIGHT : skin.hints.mainwin_height; + mainwin->resize (width, height); - int width = shaded ? MAINWIN_SHADED_WIDTH : active_skin->properties.mainwin_width; - int height = shaded ? MAINWIN_SHADED_HEIGHT : active_skin->properties.mainwin_height; - window_set_size (mainwin, width, height); + if (config.autoscroll) + mainwin_info->set_scroll (! shaded); } void view_set_playlist_shaded (bool shaded) @@ -121,16 +140,17 @@ void view_set_playlist_shaded (bool shaded) view_apply_playlist_shaded (); } -void view_apply_playlist_shaded (void) +void view_apply_playlist_shaded () { bool shaded = aud_get_bool ("skins", "playlist_shaded"); - window_set_shaded (playlistwin, shaded); + playlistwin->set_shaded (shaded); int height = shaded ? MAINWIN_SHADED_HEIGHT : config.playlist_height; - window_set_size (playlistwin, config.playlist_width, height); + playlistwin->resize (config.playlist_width, height); - playlistwin_update (); + if (config.autoscroll) + playlistwin_sinfo->set_scroll (shaded); } void view_set_equalizer_shaded (bool shaded) @@ -141,12 +161,16 @@ void view_set_equalizer_shaded (bool shaded) view_apply_equalizer_shaded (); } -void view_apply_equalizer_shaded (void) +void view_apply_equalizer_shaded () { bool shaded = aud_get_bool ("skins", "equalizer_shaded"); - window_set_shaded (equalizerwin, shaded); - window_set_size (equalizerwin, 275, shaded ? 14 : 116); + /* do not allow shading the equalizer if eq_ex.bmp is missing */ + if (! skin.pixmaps[SKIN_EQ_EX]) + shaded = false; + + equalizerwin->set_shaded (shaded); + equalizerwin->resize (275, shaded ? 14 : 116); } void view_set_double_size (bool double_size) @@ -157,10 +181,10 @@ void view_set_double_size (bool double_size) view_apply_double_size (); } -void view_apply_double_size (void) +void view_apply_double_size () { - config.scale = aud_get_bool ("skins", "double_size") ? 2 : 1; - skins_restart (); + static QueuedFunc restart; + restart.queue ((QueuedFunc::Func) skins_restart, nullptr); } void view_set_on_top (bool on_top) @@ -171,15 +195,15 @@ void view_set_on_top (bool on_top) view_apply_on_top (); } -void view_apply_on_top (void) +void view_apply_on_top () { bool on_top = aud_get_bool ("skins", "always_on_top"); - gtk_window_set_keep_above ((GtkWindow *) mainwin, on_top); - gtk_window_set_keep_above ((GtkWindow *) equalizerwin, on_top); - gtk_window_set_keep_above ((GtkWindow *) playlistwin, on_top); + gtk_window_set_keep_above ((GtkWindow *) mainwin->gtk (), on_top); + gtk_window_set_keep_above ((GtkWindow *) equalizerwin->gtk (), on_top); + gtk_window_set_keep_above ((GtkWindow *) playlistwin->gtk (), on_top); - ui_skinned_menurow_update (mainwin_menurow); + mainwin_menurow->refresh (); } void view_set_sticky (bool sticky) @@ -190,21 +214,21 @@ void view_set_sticky (bool sticky) view_apply_sticky (); } -void view_apply_sticky (void) +void view_apply_sticky () { bool sticky = aud_get_bool ("skins", "sticky"); if (sticky) { - gtk_window_stick ((GtkWindow *) mainwin); - gtk_window_stick ((GtkWindow *) equalizerwin); - gtk_window_stick ((GtkWindow *) playlistwin); + gtk_window_stick ((GtkWindow *) mainwin->gtk ()); + gtk_window_stick ((GtkWindow *) equalizerwin->gtk ()); + gtk_window_stick ((GtkWindow *) playlistwin->gtk ()); } else { - gtk_window_unstick ((GtkWindow *) mainwin); - gtk_window_unstick ((GtkWindow *) equalizerwin); - gtk_window_unstick ((GtkWindow *) playlistwin); + gtk_window_unstick ((GtkWindow *) mainwin->gtk ()); + gtk_window_unstick ((GtkWindow *) equalizerwin->gtk ()); + gtk_window_unstick ((GtkWindow *) playlistwin->gtk ()); } } @@ -216,7 +240,47 @@ void view_set_show_remaining (bool remaining) view_apply_show_remaining (); } -void view_apply_show_remaining (void) +void view_apply_show_remaining () { mainwin_update_song_info (); } + +static GdkRegion * scale_mask (const Index<GdkRectangle> & mask, int scale) +{ + GdkRegion * region = nullptr; + + for (auto & rect : mask) + { + GdkRectangle scaled = { + rect.x * scale, + rect.y * scale, + rect.width * scale, + rect.height * scale + }; + + if (region) + gdk_region_union_with_rect (region, & scaled); + else + region = gdk_region_rectangle (& scaled); + } + + return region; +} + +void view_apply_skin () +{ + mainwin->set_shapes + (scale_mask (skin.masks[SKIN_MASK_MAIN], config.scale), + scale_mask (skin.masks[SKIN_MASK_MAIN_SHADE], config.scale)); + equalizerwin->set_shapes + (scale_mask (skin.masks[SKIN_MASK_EQ], config.scale), + scale_mask (skin.masks[SKIN_MASK_EQ_SHADE], config.scale)); + + mainwin_refresh_hints (); + view_apply_equalizer_shaded (); + TextBox::update_all (); + + mainwin->queue_draw (); + equalizerwin->queue_draw (); + playlistwin->queue_draw (); +} diff --git a/src/skins/view.h b/src/skins/view.h index 18de79c..227645d 100644 --- a/src/skins/view.h +++ b/src/skins/view.h @@ -25,30 +25,32 @@ void view_show_player (bool show); void view_set_show_playlist (bool show); -void view_apply_show_playlist (void); +void view_apply_show_playlist (); void view_set_show_equalizer (bool show); -void view_apply_show_equalizer (void); +void view_apply_show_equalizer (); void view_set_player_shaded (bool shaded); -void view_apply_player_shaded (void); +void view_apply_player_shaded (); void view_set_playlist_shaded (bool shaded); -void view_apply_playlist_shaded (void); +void view_apply_playlist_shaded (); void view_set_equalizer_shaded (bool shaded); -void view_apply_equalizer_shaded (void); +void view_apply_equalizer_shaded (); void view_set_double_size (bool double_size); -void view_apply_double_size (void); +void view_apply_double_size (); void view_set_on_top (bool on_top); -void view_apply_on_top (void); +void view_apply_on_top (); void view_set_sticky (bool sticky); -void view_apply_sticky (void); +void view_apply_sticky (); void view_set_show_remaining (bool remaining); -void view_apply_show_remaining (void); +void view_apply_show_remaining (); + +void view_apply_skin (); #endif /* SKINS_VIEW_H */ diff --git a/src/skins/vis-callbacks.cc b/src/skins/vis-callbacks.cc new file mode 100644 index 0000000..a78b9c8 --- /dev/null +++ b/src/skins/vis-callbacks.cc @@ -0,0 +1,222 @@ +/* + * Audacious + * Copyright (c) 2006-2007 Audacious development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#include <math.h> + +#include <libaudcore/drct.h> +#include <libaudcore/hook.h> +#include <libaudcore/i18n.h> +#include <libaudcore/interface.h> +#include <libaudcore/runtime.h> + +#include "skins_cfg.h" +#include "main.h" +#include "vis-callbacks.h" +#include "skin.h" +#include "button.h" +#include "hslider.h" +#include "number.h" +#include "playstatus.h" +#include "textbox.h" +#include "vis.h" +#include "util.h" + +class VisCallbacks : public Visualizer +{ +public: + constexpr VisCallbacks () : + Visualizer (MonoPCM | MultiPCM | Freq) {} + + void clear (); + void render_mono_pcm (const float * pcm); + void render_multi_pcm (const float * pcm, int channels); + void render_freq (const float * freq); +}; + +void VisCallbacks::clear () +{ + mainwin_vis->clear (); + mainwin_svis->clear (); +} + +void VisCallbacks::render_mono_pcm (const float * pcm) +{ + unsigned char data[512]; + + if (config.vis_type != VIS_SCOPE) + return; + + for (int i = 0; i < 75; i ++) + { + /* the signal is amplified by 2x */ + /* output values are in the range 0 to 16 */ + int val = 8 + roundf (16 * pcm[i * 512 / 75]); + data[i] = aud::clamp (val, 0, 16); + } + + if (aud_get_bool ("skins", "player_shaded")) + mainwin_svis->render (data); + else + mainwin_vis->render (data); +} + +/* calculate peak dB level, where 1 is 0 dB */ +static float calc_peak_level (const float * pcm, int step) +{ + float peak = 0.0001; /* must be > 0, or level = -inf */ + + for (int i = 0; i < 512; i ++) + { + peak = aud::max (peak, * pcm); + pcm += step; + } + + return 20 * log10 (peak); +} + +void VisCallbacks::render_multi_pcm (const float * pcm, int channels) +{ + /* "VU meter" */ + if (config.vis_type != VIS_VOICEPRINT || ! aud_get_bool ("skins", "player_shaded")) + return; + + unsigned char data[512]; + + int level = 38 + calc_peak_level (pcm, channels); + data[0] = aud::clamp (level, 0, 38); + + if (channels >= 2) + { + level = 38 + calc_peak_level (pcm + 1, channels); + data[1] = aud::clamp (level, 0, 38); + } + else + data[1] = data[0]; + + mainwin_svis->render (data); +} + +/* convert linear frequency graph to logarithmic one */ +static void make_log_graph (const float * freq, int bands, int db_range, + int int_range, unsigned char * graph) +{ + static int last_bands = 0; + static Index<float> xscale; + + /* conversion table for the x-axis */ + if (bands != last_bands) + { + xscale.resize (bands + 1); + for (int i = 0; i <= bands; i ++) + xscale[i] = powf (256, (float) i / bands) - 0.5f; + + last_bands = bands; + } + + for (int i = 0; i < bands; i ++) + { + /* sum up values in freq array between xscale[i] and xscale[i + 1], + including fractional parts */ + int a = ceilf (xscale[i]); + int b = floorf (xscale[i + 1]); + float sum = 0; + + if (b < a) + sum += freq[b] * (xscale[i + 1] - xscale[i]); + else + { + if (a > 0) + sum += freq[a - 1] * (a - xscale[i]); + for (; a < b; a ++) + sum += freq[a]; + if (b < 256) + sum += freq[b] * (xscale[i + 1] - b); + } + + /* fudge factor to make the graph have the same overall height as a + 12-band one no matter how many bands there are */ + sum *= (float) bands / 12; + + /* convert to dB */ + float val = 20 * log10f (sum); + + /* scale (-db_range, 0.0) to (0.0, int_range) */ + val = (1 + val / db_range) * int_range; + + graph[i] = aud::clamp ((int) val, 0, int_range); + } +} + +void VisCallbacks::render_freq (const float * freq) +{ + bool shaded = aud_get_bool ("skins", "player_shaded"); + + unsigned char data[512]; + + if (config.vis_type == VIS_ANALYZER) + { + if (config.analyzer_type == ANALYZER_BARS) + { + if (shaded) + make_log_graph (freq, 13, 40, 8, data); + else + make_log_graph (freq, 19, 40, 16, data); + } + else + { + if (shaded) + make_log_graph (freq, 37, 40, 8, data); + else + make_log_graph (freq, 75, 40, 16, data); + } + } + else if (config.vis_type == VIS_VOICEPRINT && ! shaded) + make_log_graph (freq, 17, 40, 255, data); + else + return; + + if (shaded) + mainwin_svis->render (data); + else + mainwin_vis->render (data); +} + +void start_stop_visual (bool exiting) +{ + static VisCallbacks callbacks; + static bool started = false; + + if (config.vis_type != VIS_OFF && ! exiting && aud_ui_is_shown ()) + { + if (! started) + { + aud_visualizer_add (& callbacks); + started = true; + } + } + else + { + if (started) + { + aud_visualizer_remove (& callbacks); + started = false; + } + } +} diff --git a/src/skins/vis-callbacks.h b/src/skins/vis-callbacks.h new file mode 100644 index 0000000..56addbc --- /dev/null +++ b/src/skins/vis-callbacks.h @@ -0,0 +1,26 @@ +/* + * Audacious + * Copyright (c) 2006-2007 Audacious development team. + * + * 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; under version 3 of the License. + * + * 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 <http://www.gnu.org/licenses>. + * + * The Audacious team does not consider modular code linking to + * Audacious or using our public API to be a derived work. + */ + +#ifndef SKINS_UI_MAIN_EVLISTENERS_H +#define SKINS_UI_MAIN_EVLISTENERS_H + +void start_stop_visual (bool exiting); + +#endif /* SKINS_UI_MAIN_EVLISTENERS_H */ diff --git a/src/skins/ui_vis.cc b/src/skins/vis.cc index c5c3ee3..88bc78d 100644 --- a/src/skins/ui_vis.cc +++ b/src/skins/vis.cc @@ -27,41 +27,25 @@ #include <string.h> #include <libaudcore/objects.h> -#include "draw-compat.h" #include "skins_cfg.h" -#include "surface.h" -#include "ui_skin.h" -#include "ui_vis.h" +#include "skin.h" +#include "vis.h" static const float vis_afalloff_speeds[] = {0.34, 0.5, 1.0, 1.3, 1.6}; static const float vis_pfalloff_speeds[] = {1.2, 1.3, 1.4, 1.5, 1.6}; static const int vis_scope_colors[16] = {22, 22, 21, 21, 20, 10, 19, 19, 18, 19, 19, 20, 20, 21, 21, 22}; -static uint32_t vis_voice_color[256]; -static uint32_t vis_voice_color_fire[256]; -static uint32_t vis_voice_color_ice[256]; -static uint32_t pattern_fill[76 * 2]; - -static struct { - gboolean active; - float data[75], peak[75], peak_speed[75]; - unsigned char voiceprint_data[76 * 16]; - gboolean voiceprint_advance; -} vis; - #define RGB_SEEK(x,y) (set = rgb + 76 * (y) + (x)) #define RGB_SET(c) (* set ++ = (c)) #define RGB_SET_Y(c) do {* set = (c); set += 76;} while (0) -#define RGB_SET_INDEX(c) RGB_SET (active_skin->vis_colors[c]) -#define RGB_SET_INDEX_Y(c) RGB_SET_Y (active_skin->vis_colors[c]) +#define RGB_SET_INDEX(c) RGB_SET (skin.vis_colors[c]) +#define RGB_SET_INDEX_Y(c) RGB_SET_Y (skin.vis_colors[c]) -void ui_vis_set_colors (void) +void SkinnedVis::set_colors () { - g_return_if_fail (active_skin != nullptr); - - uint32_t fgc = active_skin->colors[SKIN_TEXTFG]; - uint32_t bgc = active_skin->colors[SKIN_TEXTBG]; + uint32_t fgc = skin.colors[SKIN_TEXTFG]; + uint32_t bgc = skin.colors[SKIN_TEXTBG]; int fg[3] = {COLOR_R (fgc), COLOR_G (fgc), COLOR_B (fgc)}; int bg[3] = {COLOR_R (bgc), COLOR_G (bgc), COLOR_B (bgc)}; @@ -70,7 +54,7 @@ void ui_vis_set_colors (void) unsigned char c[3]; for (int n = 0; n < 3; n ++) c[n] = bg[n] + (fg[n] - bg[n]) * x / 255; - vis_voice_color[x] = COLOR (c[0], c[1], c[2]); + m_voice_color[x] = COLOR (c[0], c[1], c[2]); } for (int x = 0; x < 256; x ++) @@ -78,13 +62,13 @@ void ui_vis_set_colors (void) unsigned char r = aud::min (x, 127) * 2; unsigned char g = aud::clamp (x - 64, 0, 127) * 2; unsigned char b = aud::max (x - 128, 0) * 2; - vis_voice_color_fire[x] = COLOR (r, g, b); + m_voice_color_fire[x] = COLOR (r, g, b); } for (int x = 0; x < 256; x ++) - vis_voice_color_ice[x] = COLOR (x / 2, x, aud::min (x * 2, 255)); + m_voice_color_ice[x] = COLOR (x / 2, x, aud::min (x * 2, 255)); - uint32_t * set = pattern_fill; + uint32_t * set = m_pattern_fill; uint32_t * end = set + 76; while (set < end) @@ -99,28 +83,29 @@ void ui_vis_set_colors (void) } } -DRAW_FUNC_BEGIN (ui_vis_draw) +void SkinnedVis::draw (cairo_t * cr) +{ uint32_t rgb[76 * 16]; uint32_t * set; if (config.vis_type != VIS_VOICEPRINT) { for (set = rgb; set < rgb + 76 * 16; set += 76 * 2) - memcpy (set, pattern_fill, sizeof pattern_fill); + memcpy (set, m_pattern_fill, sizeof m_pattern_fill); } switch (config.vis_type) { case VIS_ANALYZER: { - gboolean bars = (config.analyzer_type == ANALYZER_BARS); + bool bars = (config.analyzer_type == ANALYZER_BARS); for (int x = 0; x < 75; x ++) { if (bars && (x & 3) == 3) continue; - int h = vis.data[bars ? (x >> 2) : x]; + int h = m_data[bars ? (x >> 2) : x]; h = aud::clamp (h, 0, 16); RGB_SEEK (x, 16 - h); @@ -142,7 +127,7 @@ DRAW_FUNC_BEGIN (ui_vis_draw) if (config.analyzer_peaks) { - int h = vis.peak[bars ? (x >> 2) : x]; + int h = m_peak[bars ? (x >> 2) : x]; h = aud::clamp (h, 0, 16); if (h) @@ -157,20 +142,20 @@ DRAW_FUNC_BEGIN (ui_vis_draw) } case VIS_VOICEPRINT: { - if (vis.voiceprint_advance) + if (m_voiceprint_advance) { - vis.voiceprint_advance = FALSE; - memmove (vis.voiceprint_data, vis.voiceprint_data + 1, sizeof - vis.voiceprint_data - 1); + m_voiceprint_advance = false; + memmove (m_voiceprint_data, m_voiceprint_data + 1, sizeof + m_voiceprint_data - 1); for (int y = 0; y < 16; y ++) - vis.voiceprint_data[76 * y + 75] = vis.data[y]; + m_voiceprint_data[76 * y + 75] = m_data[y]; } - unsigned char * get = vis.voiceprint_data; + unsigned char * get = m_voiceprint_data; uint32_t * colors = (config.voiceprint_mode == VOICEPRINT_NORMAL) ? - vis_voice_color : (config.voiceprint_mode == VOICEPRINT_FIRE) ? - vis_voice_color_fire : /* VOICEPRINT_ICE */ vis_voice_color_ice; + m_voice_color : (config.voiceprint_mode == VOICEPRINT_FIRE) ? + m_voice_color_fire : /* VOICEPRINT_ICE */ m_voice_color_ice; set = rgb; for (int y = 0; y < 16; y ++) @@ -179,7 +164,7 @@ DRAW_FUNC_BEGIN (ui_vis_draw) break; } case VIS_SCOPE: - if (! vis.active) + if (! m_active) goto DRAW; switch (config.scope_mode) @@ -187,20 +172,26 @@ DRAW_FUNC_BEGIN (ui_vis_draw) case SCOPE_DOT: for (int x = 0; x < 75; x ++) { - int h = aud::clamp ((int) vis.data[x], 0, 15); + int h = aud::clamp ((int) m_data[x], 0, 15); RGB_SEEK (x, h); RGB_SET_INDEX (vis_scope_colors[h]); } break; case SCOPE_LINE: { - for (int x = 0; x < 74; x++) + for (int x = 0; x < 74; x ++) { - int h = aud::clamp ((int) vis.data[x], 0, 15); - int h2 = aud::clamp ((int) vis.data[x + 1], 0, 15); + int h = aud::clamp ((int) m_data[x], 0, 15); + int h2 = aud::clamp ((int) m_data[x + 1], 0, 15); - if (h < h2) h2 --; - else if (h > h2) {int temp = h; h = h2 + 1; h2 = temp;} + if (h < h2) + h2 --; + else if (h > h2) + { + int temp = h; + h = h2 + 1; + h2 = temp; + } RGB_SEEK (x, h); @@ -208,19 +199,24 @@ DRAW_FUNC_BEGIN (ui_vis_draw) RGB_SET_INDEX_Y (vis_scope_colors[y]); } - int h = aud::clamp ((int) vis.data[74], 0, 15); + int h = aud::clamp ((int) m_data[74], 0, 15); RGB_SEEK (74, h); RGB_SET_INDEX (vis_scope_colors[h]); break; } default: /* SCOPE_SOLID */ - for (int x = 0; x < 75; x++) + for (int x = 0; x < 75; x ++) { - int h = aud::clamp ((int) vis.data[x], 0, 15); + int h = aud::clamp ((int) m_data[x], 0, 15); int h2; - if (h < 8) h2 = 8; - else {h2 = h; h = 8;} + if (h < 8) + h2 = 8; + else + { + h2 = h; + h = 8; + } RGB_SEEK (x, h); @@ -232,94 +228,95 @@ DRAW_FUNC_BEGIN (ui_vis_draw) break; } -DRAW:; +DRAW: cairo_surface_t * surf = cairo_image_surface_create_for_data ((unsigned char *) rgb, CAIRO_FORMAT_RGB24, 76, 16, 4 * 76); - cairo_scale (cr, config.scale, config.scale); cairo_set_source_surface (cr, surf, 0, 0); cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST); cairo_paint (cr); cairo_surface_destroy (surf); -DRAW_FUNC_END +} -GtkWidget * ui_vis_new (void) +SkinnedVis::SkinnedVis () { - GtkWidget * wid = gtk_drawing_area_new (); - gtk_widget_set_size_request (wid, 76 * config.scale, 16 * config.scale); - gtk_widget_add_events (wid, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); - DRAW_CONNECT (wid, ui_vis_draw); - return wid; + set_scale (config.scale); + add_drawable (76, 16); + clear (); } -void ui_vis_clear_data (GtkWidget * wid) +void SkinnedVis::clear () { - memset (& vis, 0, sizeof vis); - gtk_widget_queue_draw (wid); + m_active = false; + m_voiceprint_advance = false; + + memset (m_data, 0, sizeof m_data); + memset (m_peak, 0, sizeof m_peak); + memset (m_peak_speed, 0, sizeof m_peak_speed); + memset (m_voiceprint_data, 0, sizeof m_voiceprint_data); + + queue_draw (); } -void ui_vis_timeout_func (GtkWidget * widget, unsigned char * data) +void SkinnedVis::render (const unsigned char * data) { if (config.vis_type == VIS_ANALYZER) { const int n = (config.analyzer_type == ANALYZER_BARS) ? 19 : 75; - for (int i = 0; i < n; i++) + for (int i = 0; i < n; i ++) { - if (data[i] > vis.data[i]) + if (data[i] > m_data[i]) { - vis.data[i] = data[i]; - if (vis.data[i] > vis.peak[i]) + m_data[i] = data[i]; + if (m_data[i] > m_peak[i]) { - vis.peak[i] = vis.data[i]; - vis.peak_speed[i] = 0.01; + m_peak[i] = m_data[i]; + m_peak_speed[i] = 0.01; } - else if (vis.peak[i] > 0.0) + else if (m_peak[i] > 0.0) { - vis.peak[i] -= vis.peak_speed[i]; - vis.peak_speed[i] *= - vis_pfalloff_speeds[config.peaks_falloff]; - if (vis.peak[i] < vis.data[i]) - vis.peak[i] = vis.data[i]; - if (vis.peak[i] < 0.0) - vis.peak[i] = 0.0; + m_peak[i] -= m_peak_speed[i]; + m_peak_speed[i] *= vis_pfalloff_speeds[config.peaks_falloff]; + if (m_peak[i] < m_data[i]) + m_peak[i] = m_data[i]; + if (m_peak[i] < 0.0) + m_peak[i] = 0.0; } } else { - if (vis.data[i] > 0.0) + if (m_data[i] > 0.0) { - vis.data[i] -= - vis_afalloff_speeds[config.analyzer_falloff]; - if (vis.data[i] < 0.0) - vis.data[i] = 0.0; + m_data[i] -= vis_afalloff_speeds[config.analyzer_falloff]; + if (m_data[i] < 0.0) + m_data[i] = 0.0; } - if (vis.peak[i] > 0.0) + if (m_peak[i] > 0.0) { - vis.peak[i] -= vis.peak_speed[i]; - vis.peak_speed[i] *= - vis_pfalloff_speeds[config.peaks_falloff]; - if (vis.peak[i] < vis.data[i]) - vis.peak[i] = vis.data[i]; - if (vis.peak[i] < 0.0) - vis.peak[i] = 0.0; + m_peak[i] -= m_peak_speed[i]; + m_peak_speed[i] *= vis_pfalloff_speeds[config.peaks_falloff]; + if (m_peak[i] < m_data[i]) + m_peak[i] = m_data[i]; + if (m_peak[i] < 0.0) + m_peak[i] = 0.0; } } } } else if (config.vis_type == VIS_VOICEPRINT) { - for (int i = 0; i < 16; i++) - vis.data[i] = data[15 - i]; + for (int i = 0; i < 16; i ++) + m_data[i] = data[15 - i]; - vis.voiceprint_advance = TRUE; + m_voiceprint_advance = true; } else { - for (int i = 0; i < 75; i++) - vis.data[i] = data[i]; + for (int i = 0; i < 75; i ++) + m_data[i] = data[i]; } - vis.active = TRUE; - gtk_widget_queue_draw (widget); + m_active = true; + draw_now (); } diff --git a/src/skins/ui_vis.h b/src/skins/vis.h index e3d753a..899c5e3 100644 --- a/src/skins/ui_vis.h +++ b/src/skins/vis.h @@ -21,7 +21,8 @@ #ifndef SKINS_UI_VIS_H #define SKINS_UI_VIS_H -#include <gtk/gtk.h> +#include <stdint.h> +#include "widget.h" typedef enum { VIS_ANALYZER, VIS_SCOPE, VIS_VOICEPRINT, VIS_OFF @@ -51,13 +52,39 @@ typedef enum { FALLOFF_SLOWEST, FALLOFF_SLOW, FALLOFF_MEDIUM, FALLOFF_FAST, FALLOFF_FASTEST } FalloffSpeed; -GtkWidget * ui_vis_new (void); -void ui_vis_set_colors (void); -void ui_vis_clear_data (GtkWidget * widget); -void ui_vis_timeout_func (GtkWidget * widget, unsigned char * data); +class SkinnedVis : public Widget +{ +public: + SkinnedVis (); + void set_colors (); + void clear (); + void render (const unsigned char * data); -GtkWidget * ui_svis_new (void); -void ui_svis_clear_data (GtkWidget * widget); -void ui_svis_timeout_func (GtkWidget * widget, unsigned char * data); +private: + void draw (cairo_t * cr); + + uint32_t m_voice_color[256]; + uint32_t m_voice_color_fire[256]; + uint32_t m_voice_color_ice[256]; + uint32_t m_pattern_fill[76 * 2]; + + bool m_active, m_voiceprint_advance; + float m_data[75], m_peak[75], m_peak_speed[75]; + unsigned char m_voiceprint_data[76 * 16]; +}; + +class SmallVis : public Widget +{ +public: + SmallVis (); + void clear (); + void render (const unsigned char * data); + +private: + void draw (cairo_t * cr); + + bool m_active; + int m_data[75]; +}; #endif diff --git a/src/skins/widget.cc b/src/skins/widget.cc new file mode 100644 index 0000000..dc1e58b --- /dev/null +++ b/src/skins/widget.cc @@ -0,0 +1,125 @@ +/* + * widget.cc + * Copyright 2015 John Lindgren + * + * This file is part of Audacious. + * + * Audacious 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, version 2 or version 3 of the License. + * + * Audacious 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 + * Audacious. If not, see <http://www.gnu.org/licenses/>. + * + * The Audacious team does not consider modular code linking to Audacious or + * using our public API to be a derived work. + */ + +#include "widget.h" + +typedef GtkWidget DrawingArea; +typedef GtkWidgetClass DrawingAreaClass; + +G_DEFINE_TYPE (DrawingArea, drawing_area, GTK_TYPE_WIDGET) + +static void drawing_area_class_init (DrawingAreaClass *) {} + +static void drawing_area_init (DrawingArea * widget) +{ + gtk_widget_set_has_window ((GtkWidget *) widget, false); +} + +static GtkWidget * drawing_area_new () +{ + return (GtkWidget *) g_object_new (drawing_area_get_type (), nullptr); +} + +void Widget::set_input (GtkWidget * widget) +{ + m_widget = widget; + g_signal_connect (widget, "destroy", (GCallback) Widget::destroy_cb, this); + g_signal_connect (widget, "key-press-event", (GCallback) Widget::keypress_cb, this); + g_signal_connect (widget, "button-press-event", (GCallback) Widget::button_press_cb, this); + g_signal_connect (widget, "button-release-event", (GCallback) Widget::button_release_cb, this); + g_signal_connect (widget, "scroll-event", (GCallback) Widget::scroll_cb, this); + g_signal_connect (widget, "motion-notify-event", (GCallback) Widget::motion_cb, this); + g_signal_connect (widget, "leave-notify-event", (GCallback) Widget::leave_cb, this); + g_signal_connect (widget, "delete-event", (GCallback) Widget::close_cb, this); +} + +void Widget::set_drawable (GtkWidget * widget) +{ + m_drawable = widget; + g_signal_connect (widget, "realize", (GCallback) Widget::realize_cb, this); + g_signal_connect (widget, "expose-event", (GCallback) Widget::draw_cb, this); + + if (! m_widget) + { + m_widget = widget; + g_signal_connect (widget, "destroy", (GCallback) Widget::destroy_cb, this); + } +} + +void Widget::add_input (int width, int height, bool track_motion, bool drawable) +{ + int events = GDK_KEY_PRESS_MASK | GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK | GDK_SCROLL_MASK; + + if (track_motion) + events |= GDK_POINTER_MOTION_MASK | GDK_LEAVE_NOTIFY_MASK; + + GtkWidget * widget = gtk_event_box_new (); + gtk_event_box_set_visible_window ((GtkEventBox *) widget, false); + gtk_widget_set_size_request (widget, width * m_scale, height * m_scale); + gtk_widget_add_events (widget, events); + gtk_widget_show (widget); + set_input (widget); + + if (drawable) + { + GtkWidget * area = drawing_area_new (); + gtk_container_add ((GtkContainer *) widget, area); + gtk_widget_show (area); + set_drawable (area); + } +} + +void Widget::add_drawable (int width, int height) +{ + GtkWidget * widget = drawing_area_new (); + gtk_widget_set_size_request (widget, width * m_scale, height * m_scale); + gtk_widget_show (widget); + set_drawable (widget); +} + +void Widget::draw_now () +{ + if (m_drawable && gtk_widget_is_drawable (m_drawable)) + draw_cb (m_drawable, nullptr, this); +} + +gboolean Widget::draw_cb (GtkWidget * widget, GdkEventExpose * event, Widget * me) +{ + cairo_t * cr = gdk_cairo_create (gtk_widget_get_window (widget)); + + if (! gtk_widget_get_has_window (widget)) + { + GtkAllocation alloc; + gtk_widget_get_allocation (widget, & alloc); + cairo_translate (cr, alloc.x, alloc.y); + cairo_rectangle (cr, 0, 0, alloc.width, alloc.height); + cairo_clip (cr); + } + + if (me->m_scale != 1) + cairo_scale (cr, me->m_scale, me->m_scale); + + me->draw (cr); + + cairo_destroy (cr); + return false; +} diff --git a/src/skins/widget.h b/src/skins/widget.h new file mode 100644 index 0000000..057b8c7 --- /dev/null +++ b/src/skins/widget.h @@ -0,0 +1,93 @@ +/* + * widget.h + * Copyright 2015 John Lindgren + * + * This file is part of Audacious. + * + * Audacious 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, version 2 or version 3 of the License. + * + * Audacious 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 + * Audacious. If not, see <http://www.gnu.org/licenses/>. + * + * The Audacious team does not consider modular code linking to Audacious or + * using our public API to be a derived work. + */ + +#ifndef SKINS_WIDGET_H +#define SKINS_WIDGET_H + +#include <gtk/gtk.h> + +class Widget +{ +public: + virtual ~Widget () {} + + GtkWidget * gtk () { return m_widget; } + GtkWidget * gtk_dr () { return m_drawable; } + + void show () { gtk_widget_show (m_widget); } + void hide () { gtk_widget_hide (m_widget); } + + void setVisible (bool visible) + { gtk_widget_set_visible (m_widget, visible); } + void queue_draw () + { gtk_widget_queue_draw (m_drawable); } + +protected: + void set_input (GtkWidget * widget); + void set_drawable (GtkWidget * widget); + void add_input (int width, int height, bool track_motion, bool drawable); + void add_drawable (int width, int height); + + void set_scale (int scale) { m_scale = scale; } + void resize (int width, int height) + { gtk_widget_set_size_request (m_widget, width * m_scale, height * m_scale); } + + void draw_now (); + + virtual void realize () {} + virtual void draw (cairo_t * cr) {} + virtual bool keypress (GdkEventKey * event) { return false; } + virtual bool button_press (GdkEventButton * event) { return false; } + virtual bool button_release (GdkEventButton * event) { return false; } + virtual bool scroll (GdkEventScroll * event) { return false; } + virtual bool motion (GdkEventMotion * event) { return false; } + virtual bool leave () { return false; } + virtual bool close () { return false; } + +private: + static void destroy_cb (GtkWidget * widget, Widget * me) + { delete me; } + static void realize_cb (GtkWidget * widget, Widget * me) + { me->realize (); } + + static gboolean draw_cb (GtkWidget * widget, GdkEventExpose * event, Widget * me); + + static gboolean keypress_cb (GtkWidget * widget, GdkEventKey * event, Widget * me) + { return me->keypress (event); } + static gboolean button_press_cb (GtkWidget * widget, GdkEventButton * event, Widget * me) + { return me->button_press (event); } + static gboolean button_release_cb (GtkWidget * widget, GdkEventButton * event, Widget * me) + { return me->button_release (event); } + static gboolean scroll_cb (GtkWidget * widget, GdkEventScroll * event, Widget * me) + { return me->scroll (event); } + static gboolean motion_cb (GtkWidget * widget, GdkEventMotion * event, Widget * me) + { return me->motion (event); } + static gboolean leave_cb (GtkWidget * widget, GdkEventCrossing * event, Widget * me) + { return me->leave (); } + static gboolean close_cb (GtkWidget * widget, GdkEvent * event, Widget * me) + { return me->close (); } + + GtkWidget * m_widget = nullptr; + GtkWidget * m_drawable = nullptr; + int m_scale = 1; +}; + +#endif // SKINS_WIDGET_H diff --git a/src/skins/window.cc b/src/skins/window.cc new file mode 100644 index 0000000..48aa0f3 --- /dev/null +++ b/src/skins/window.cc @@ -0,0 +1,184 @@ +/* + * ui_skinned_window.c + * Copyright 2011 John Lindgren + * + * This file is part of Audacious. + * + * Audacious 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, version 2 or version 3 of the License. + * + * Audacious 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 + * Audacious. If not, see <http://www.gnu.org/licenses/>. + * + * The Audacious team does not consider modular code linking to Audacious or + * using our public API to be a derived work. + */ + +#include "window.h" +#include "menus.h" +#include "plugin.h" +#include "skins_cfg.h" + +void Window::apply_shape () +{ + if (gtk_widget_get_realized (gtk ())) + gdk_window_shape_combine_region (gtk_widget_get_window (gtk ()), + m_is_shaded ? m_sshape.get () : m_shape.get (), 0, 0); +} + +void Window::realize () +{ + gdk_window_set_back_pixmap (gtk_widget_get_window (gtk ()), nullptr, false); + apply_shape (); +} + +bool Window::button_press (GdkEventButton * event) +{ + /* pass double clicks through; they are handled elsewhere */ + if (event->button != 1 || event->type == GDK_2BUTTON_PRESS) + return false; + + if (m_is_moving) + return true; + + dock_move_start (m_id, event->x_root, event->y_root); + m_is_moving = true; + return true; +} + +bool Window::button_release (GdkEventButton * event) +{ + if (event->button != 1) + return false; + + m_is_moving = false; + return true; +} + +bool Window::motion (GdkEventMotion * event) +{ + if (! m_is_moving) + return true; + + dock_move (event->x_root, event->y_root); + return true; +} + +bool Window::close () +{ + skins_close (); + return true; +} + +Window::~Window () +{ + dock_remove_window (m_id); + + g_object_unref (m_normal); + g_object_unref (m_shaded); +} + +Window::Window (int id, int * x, int * y, int w, int h, bool shaded) : + m_id (id), + m_is_shaded (shaded) +{ + w *= config.scale; + h *= config.scale; + + GtkWidget * window = gtk_window_new (GTK_WINDOW_TOPLEVEL); + gtk_window_set_decorated ((GtkWindow *) window, false); + gtk_window_set_resizable ((GtkWindow *) window, false); + gtk_window_move ((GtkWindow *) window, * x, * y); + gtk_widget_set_size_request (window, w, h); + gtk_window_resize ((GtkWindow *) window, w, h); + + if (id != WINDOW_MAIN) + { + gtk_window_set_skip_pager_hint ((GtkWindow *) window, true); + gtk_window_set_skip_taskbar_hint ((GtkWindow *) window, true); + } + + gtk_widget_set_app_paintable (window, true); + gtk_widget_add_events (window, GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK | GDK_SCROLL_MASK); + gtk_window_add_accel_group ((GtkWindow *) window, menu_get_accel_group ()); + + /* We set None as the background pixmap in order to avoid flickering. + * Setting a blank GtkStyle prevents GTK 2.x from overriding this. */ + GtkStyle * style = gtk_style_new (); + gtk_widget_set_style (window, style); + g_object_unref (style); + + set_input (window); + set_drawable (window); + set_scale (config.scale); + + m_normal = gtk_fixed_new (); + g_object_ref_sink (m_normal); + gtk_widget_show (m_normal); + + m_shaded = gtk_fixed_new (); + g_object_ref_sink (m_shaded); + gtk_widget_show (m_shaded); + + if (shaded) + gtk_container_add ((GtkContainer *) window, m_shaded); + else + gtk_container_add ((GtkContainer *) window, m_normal); + + dock_add_window (id, this, x, y, w, h); +} + +void Window::resize (int w, int h) +{ + w *= config.scale; + h *= config.scale; + + gtk_widget_set_size_request (gtk (), w, h); + gtk_window_resize ((GtkWindow *) gtk (), w, h); + dock_set_size (m_id, w, h); +} + +void Window::set_shapes (GdkRegion * shape, GdkRegion * sshape) +{ + m_shape.capture (shape); + m_sshape.capture (sshape); + apply_shape (); +} + +void Window::set_shaded (bool shaded) +{ + if (m_is_shaded == shaded) + return; + + if (shaded) + { + gtk_container_remove ((GtkContainer *) gtk (), m_normal); + gtk_container_add ((GtkContainer *) gtk (), m_shaded); + } + else + { + gtk_container_remove ((GtkContainer *) gtk (), m_shaded); + gtk_container_add ((GtkContainer *) gtk (), m_normal); + } + + m_is_shaded = shaded; + apply_shape (); +} + +void Window::put_widget (bool shaded, Widget * widget, int x, int y) +{ + GtkWidget * fixed = shaded ? m_shaded : m_normal; + gtk_fixed_put ((GtkFixed *) fixed, widget->gtk (), x * config.scale, y * config.scale); +} + +void Window::move_widget (bool shaded, Widget * widget, int x, int y) +{ + GtkWidget * fixed = shaded ? m_shaded : m_normal; + gtk_fixed_move ((GtkFixed *) fixed, widget->gtk (), x * config.scale, y * config.scale); +} diff --git a/src/skins/window.h b/src/skins/window.h new file mode 100644 index 0000000..d7afd3a --- /dev/null +++ b/src/skins/window.h @@ -0,0 +1,81 @@ +/* + * ui_skinned_window.h + * Copyright 2011 John Lindgren + * + * This file is part of Audacious. + * + * Audacious 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, version 2 or version 3 of the License. + * + * Audacious 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 + * Audacious. If not, see <http://www.gnu.org/licenses/>. + * + * The Audacious team does not consider modular code linking to Audacious or + * using our public API to be a derived work. + */ + +#ifndef SKINS_UI_SKINNED_WINDOW_H +#define SKINS_UI_SKINNED_WINDOW_H + +#include "widget.h" + +#include <libaudcore/objects.h> + +enum { + WINDOW_MAIN, + WINDOW_EQ, + WINDOW_PLAYLIST, + N_WINDOWS +}; + +class Window : public Widget +{ +public: + Window (int id, int * x, int * y, int w, int h, bool shaded); + ~Window (); + + void resize (int w, int h); + void set_shapes (GdkRegion * shape, GdkRegion * sshape); + bool is_shaded () { return m_is_shaded; } + void set_shaded (bool shaded); + void put_widget (bool shaded, Widget * widget, int x, int y); + void move_widget (bool shaded, Widget * widget, int x, int y); + + void setWindowTitle (const char * title) + { gtk_window_set_title ((GtkWindow *) gtk (), title); } + void getPosition (int * x, int * y) + { gtk_window_get_position ((GtkWindow *) gtk (), x, y); } + void move (int x, int y) + { gtk_window_move ((GtkWindow *) gtk (), x, y); } + +protected: + void realize (); + bool keypress (GdkEventKey * event); // in main.cc + bool button_press (GdkEventButton * event); + bool button_release (GdkEventButton * event); + bool motion (GdkEventMotion * event); + bool close (); + +private: + void apply_shape (); + + const int m_id; + bool m_is_shaded = false; + bool m_is_moving = false; + GtkWidget * m_normal = nullptr, * m_shaded = nullptr; + SmartPtr<GdkRegion, gdk_region_destroy> m_shape, m_sshape; +}; + +void dock_add_window (int id, Window * window, int * x, int * y, int w, int h); +void dock_remove_window (int id); +void dock_set_size (int id, int w, int h); +void dock_move_start (int id, int x, int y); +void dock_move (int x, int y); +void dock_change_scale (int old_scale, int new_scale); + +#endif diff --git a/src/sndfile/plugin.cc b/src/sndfile/plugin.cc index dfd618f..588f024 100644 --- a/src/sndfile/plugin.cc +++ b/src/sndfile/plugin.cc @@ -59,13 +59,23 @@ EXPORT SndfilePlugin aud_plugin_instance; static sf_count_t sf_get_filelen (void *user_data) { - return ((VFSFile *) user_data)->fsize (); + int64_t size = ((VFSFile *) user_data)->fsize (); + return (size < 0) ? SF_COUNT_MAX : size; } static sf_count_t sf_vseek (sf_count_t offset, int whence, void *user_data) { - return ((VFSFile *) user_data)->fseek (offset, to_vfs_seek_type (whence)); + if (((VFSFile *) user_data)->fseek (offset, to_vfs_seek_type (whence)) != 0) + return -1; + + return ((VFSFile *) user_data)->ftell (); +} + +static sf_count_t +sf_vseek_dummy (sf_count_t offset, int whence, void *user_data) +{ + return -1; } static sf_count_t @@ -75,9 +85,9 @@ sf_vread (void *ptr, sf_count_t count, void *user_data) } static sf_count_t -sf_vwrite (const void *ptr, sf_count_t count, void *user_data) +sf_vwrite_dummy (const void *ptr, sf_count_t count, void *user_data) { - return ((VFSFile *) user_data)->fwrite (ptr, 1, count); + return 0; } static sf_count_t @@ -91,7 +101,16 @@ static SF_VIRTUAL_IO sf_virtual_io = sf_get_filelen, sf_vseek, sf_vread, - sf_vwrite, + sf_vwrite_dummy, + sf_tell +}; + +static SF_VIRTUAL_IO sf_virtual_io_stream = +{ + sf_get_filelen, + sf_vseek_dummy, + sf_vread, + sf_vwrite_dummy, sf_tell }; @@ -111,12 +130,13 @@ static void copy_int (SNDFILE * sf, int sf_id, Tuple & tup, Tuple::Field field) Tuple SndfilePlugin::read_tuple (const char * filename, VFSFile & file) { - SNDFILE *sndfile; SF_INFO sfinfo {}; // must be zeroed before sf_open() const char *format, *subformat; Tuple ti; - sndfile = sf_open_virtual (& sf_virtual_io, SFM_READ, & sfinfo, & file); + bool stream = (file.fsize () < 0); + SNDFILE * sndfile = sf_open_virtual (stream ? & sf_virtual_io_stream : + & sf_virtual_io, SFM_READ, & sfinfo, & file); if (sndfile == nullptr) return ti; @@ -287,7 +307,11 @@ Tuple SndfilePlugin::read_tuple (const char * filename, VFSFile & file) bool SndfilePlugin::play (const char * filename, VFSFile & file) { SF_INFO sfinfo {}; // must be zeroed before sf_open() - SNDFILE * sndfile = sf_open_virtual (& sf_virtual_io, SFM_READ, & sfinfo, & file); + + bool stream = (file.fsize () < 0); + SNDFILE * sndfile = sf_open_virtual (stream ? & sf_virtual_io_stream : + & sf_virtual_io, SFM_READ, & sfinfo, & file); + if (sndfile == nullptr) return false; @@ -316,11 +340,12 @@ bool SndfilePlugin::play (const char * filename, VFSFile & file) bool SndfilePlugin::is_our_file (const char * filename, VFSFile & file) { - SNDFILE *tmp_sndfile; SF_INFO tmp_sfinfo {}; // must be zeroed before sf_open() /* Have to open the file to see if libsndfile can handle it. */ - tmp_sndfile = sf_open_virtual (&sf_virtual_io, SFM_READ, &tmp_sfinfo, &file); + bool stream = (file.fsize () < 0); + SNDFILE * tmp_sndfile = sf_open_virtual (stream ? & sf_virtual_io_stream : + & sf_virtual_io, SFM_READ, & tmp_sfinfo, & file); if (!tmp_sndfile) return false; diff --git a/src/sndio-ng/sndio.cc b/src/sndio-ng/sndio.cc index 9b1d841..59301f5 100644 --- a/src/sndio-ng/sndio.cc +++ b/src/sndio-ng/sndio.cc @@ -63,9 +63,11 @@ public: int get_delay (); - void pause (bool pause); void flush (); + // not implemented + void pause (bool pause) {} + private: bool poll_locked (); @@ -77,7 +79,6 @@ private: int m_rate = 0, m_channels = 0; int m_bytes_per_frame = 0; - bool m_paused = false; int m_frames_buffered = 0; timeval m_last_write_time = timeval (); int m_flush_count = 0; @@ -197,7 +198,6 @@ bool SndioPlugin::open_audio (int format, int rate, int channels) m_channels = channels; m_bytes_per_frame = FMT_SIZEOF (format) * channels; - m_paused = false; m_frames_buffered = 0; m_last_write_time = timeval (); m_flush_count = 0; @@ -288,7 +288,7 @@ void SndioPlugin::period_wait () { pthread_mutex_lock (& m_mutex); - if (m_paused || sio_eof (m_handle) || ! poll_locked ()) + if (sio_eof (m_handle) || ! poll_locked ()) pthread_cond_wait (& m_cond, & m_mutex); pthread_mutex_unlock (& m_mutex); @@ -296,14 +296,10 @@ void SndioPlugin::period_wait () int SndioPlugin::write_audio (const void * data, int size) { - int len = 0; pthread_mutex_lock (& m_mutex); - if (! m_paused) - { - len = sio_write (m_handle, data, size); - m_frames_buffered += len / m_bytes_per_frame; - } + int len = sio_write (m_handle, data, size); + m_frames_buffered += len / m_bytes_per_frame; pthread_mutex_unlock (& m_mutex); return len; @@ -313,17 +309,14 @@ void SndioPlugin::drain () { pthread_mutex_lock (& m_mutex); - if (! m_paused) - { - int d = aud::rescale (m_frames_buffered, m_rate, 1000); - timespec delay = {d / 1000, d % 1000 * 1000000}; + int d = aud::rescale (m_frames_buffered, m_rate, 1000); + timespec delay = {d / 1000, d % 1000 * 1000000}; - pthread_mutex_unlock (& m_mutex); - nanosleep (& delay, nullptr); - pthread_mutex_lock (& m_mutex); + pthread_mutex_unlock (& m_mutex); + nanosleep (& delay, nullptr); + pthread_mutex_lock (& m_mutex); - poll_locked (); - } + poll_locked (); pthread_mutex_unlock (& m_mutex); } @@ -348,16 +341,6 @@ int SndioPlugin::get_delay () return delay; } -void SndioPlugin::pause (bool pause) -{ - pthread_mutex_lock (& m_mutex); - - m_paused = pause; - - pthread_cond_broadcast (& m_cond); - pthread_mutex_unlock (& m_mutex); -} - void SndioPlugin::flush () { pthread_mutex_lock (& m_mutex); diff --git a/src/song-info-qt/song-info.cc b/src/song-info-qt/song-info.cc index 8b26933..6f80108 100644 --- a/src/song-info-qt/song-info.cc +++ b/src/song-info-qt/song-info.cc @@ -17,11 +17,13 @@ * the use of this software. */ +#define AUD_PLUGIN_QT_ONLY #include <libaudcore/drct.h> #include <libaudcore/hook.h> #include <libaudcore/i18n.h> #include <libaudcore/playlist.h> #include <libaudcore/plugin.h> +#include <libaudcore/probe.h> #include <libaudqt/libaudqt.h> #include <libaudqt/info-widget.h> @@ -29,7 +31,7 @@ class SongInfo : public GeneralPlugin { public: static constexpr PluginInfo info = { - N_("Song Info (Qt)"), + N_("Song Info"), PACKAGE }; @@ -69,7 +71,8 @@ void SongInfo::update (void * unused, audqt::InfoWidget * widget) Tuple tuple = aud_playlist_entry_get_tuple (playlist, position); if (tuple) - widget->fillInfo (playlist, position, filename, tuple, decoder, false); + widget->fillInfo (playlist, position, filename, tuple, decoder, + aud_file_can_write_tuple (filename, decoder)); } void SongInfo::clear (void * unused, audqt::InfoWidget * widget) @@ -93,6 +96,8 @@ void * SongInfo::get_qt_widget () hook_associate ("playback begin", (HookFunction) update, widget); hook_associate ("playback stop", (HookFunction) clear, widget); + update(nullptr, widget); + return widget; } diff --git a/src/song_change/Makefile b/src/song_change/Makefile index c3b3b3a..5ae5784 100644 --- a/src/song_change/Makefile +++ b/src/song_change/Makefile @@ -10,5 +10,4 @@ plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR} LD = ${CXX} CFLAGS += ${PLUGIN_CFLAGS} -CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GTK_CFLAGS} ${GLIB_CFLAGS} -I../.. -LIBS += ${GTK_LIBS} ${GLIB_LIBS} +CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../.. diff --git a/src/song_change/formatter.cc b/src/song_change/formatter.cc index c46c075..3686cf0 100644 --- a/src/song_change/formatter.cc +++ b/src/song_change/formatter.cc @@ -22,83 +22,60 @@ * Audacious or using our public API to be a derived work. */ -#include <glib.h> +#include <assert.h> #include <string.h> #include "formatter.h" -Formatter * -formatter_new(void) +StringBuf Formatter::format (const char * format) const { - Formatter *formatter = g_slice_new0(Formatter); - - formatter_associate(formatter, '%', "%"); - return formatter; -} - -void -formatter_destroy(Formatter * formatter) -{ - int i; - - for (i = 0; i < 256; i++) - if (formatter->values[i]) - g_free(formatter->values[i]); - - g_slice_free(Formatter, formatter); -} - -void -formatter_associate(Formatter * formatter, const unsigned char id, const char *value) -{ - formatter_dissociate(formatter, id); - formatter->values[id] = g_strdup(value); -} - -void -formatter_dissociate(Formatter * formatter, const unsigned char id) -{ - if (formatter->values[id]) - g_free(formatter->values[id]); - formatter->values[id] = 0; -} - -char * -formatter_format(Formatter * formatter, const char *format) -{ - const char *p; - char *q, *buffer; + const char * p; + char * q; int len; - for (p = format, len = 0; *p; p++) - if (*p == '%') { - if (formatter->values[(int) *++p]) - len += strlen(formatter->values[(int) *p]); - else if (!*p) { + for (p = format, len = 0; * p; p ++) + { + if (* p == '%') + { + if (values[(int) * ++ p]) + len += strlen (values[(int) * p]); + else if (! * p) + { len += 1; - p--; + p --; } else len += 2; } else - len++; - buffer = g_new(char, len + 1); - for (p = format, q = buffer; *p; p++) - if (*p == '%') { - if (formatter->values[(int) *++p]) { - g_strlcpy(q, formatter->values[(int) *p], len - 1); - q += strlen(q); + len ++; + } + + StringBuf buffer (len); + + for (p = format, q = buffer; * p; p ++) + { + if (* p == '%') + { + if (values[(int) * ++ p]) + { + strcpy (q, values[(int) * p]); + q += strlen (q); } - else { - *q++ = '%'; - if (*p != '\0') - *q++ = *p; + else + { + * q ++ = '%'; + if (* p != '\0') + * q ++ = * p; else - p--; + p --; } } else - *q++ = *p; - *q = 0; + * q ++ = * p; + } + + // sanity check + assert (q == buffer + buffer.len ()); + return buffer; } diff --git a/src/song_change/formatter.h b/src/song_change/formatter.h index ec542e4..196fbc3 100644 --- a/src/song_change/formatter.h +++ b/src/song_change/formatter.h @@ -1,16 +1,20 @@ #ifndef FORMATTER_H #define FORMATTER_H -#include <glib.h> +#include <libaudcore/objects.h> -typedef struct { - char *values[256]; -} Formatter; +struct Formatter +{ + Formatter () + { set ('%', "%"); } -Formatter *formatter_new(void); -void formatter_destroy(Formatter * formatter); -void formatter_associate(Formatter * formatter, const unsigned char id, const char * value); -void formatter_dissociate(Formatter * formatter, const unsigned char id); -char *formatter_format(Formatter * formatter, const char * format); + void set (unsigned char id, const char * value) + { values[id] = String (value); } + + StringBuf format (const char * format) const; + +private: + String values[256]; +}; #endif diff --git a/src/song_change/song_change.cc b/src/song_change/song_change.cc index 10a444b..fdca5bc 100644 --- a/src/song_change/song_change.cc +++ b/src/song_change/song_change.cc @@ -2,14 +2,14 @@ * Audacious: A cross-platform multimedia player. * Copyright (c) 2005 Audacious Team */ -#include <glib.h> -#include <gtk/gtk.h> + #include <sys/types.h> #include <sys/wait.h> #include <signal.h> #include <unistd.h> +#include <assert.h> #include <string.h> #include <libaudcore/runtime.h> @@ -44,67 +44,63 @@ public: EXPORT SongChange aud_plugin_instance; -static void songchange_playback_begin(void *, void *); -static void songchange_playback_end(void *, void *); -static void songchange_playlist_eof(void *, void *); -static void songchange_playback_ttc(void *, void *); - static String cmd_line; static String cmd_line_after; static String cmd_line_end; static String cmd_line_ttc; -static GtkWidget *cmd_warn_label, *cmd_warn_img; - /** * Escapes characters that are special to the shell inside double quotes. * * @param string String to be escaped. - * @return Given string with special characters escaped. Must be freed with g_free(). + * @return Given string with special characters escaped. */ -static char *escape_shell_chars(const char * string) +static StringBuf escape_shell_chars (const char * string) { - const char *special = "$`\"\\"; /* Characters to escape */ - const char *in = string; - char *out, *escaped; + const char * special = "$`\"\\"; /* Characters to escape */ + const char * in = string; + char * out; int num = 0; - while (*in != '\0') - if (strchr(special, *in++)) - num++; + while (* in != '\0') + if (strchr (special, * in ++)) + num ++; - escaped = g_new(char, strlen(string) + num + 1); + StringBuf escaped (strlen (string) + num); in = string; out = escaped; - while (*in != '\0') { - if (strchr(special, *in)) - *out++ = '\\'; - *out++ = *in++; + while (* in != '\0') + { + if (strchr (special, * in)) + * out ++ = '\\'; + * out ++ = * in ++; } - *out = '\0'; + + // sanity check + assert (out == escaped + escaped.len ()); return escaped; } -static void bury_child(int signal) +static void bury_child (int signal) { - waitpid(-1, nullptr, WNOHANG); + waitpid (-1, nullptr, WNOHANG); } -static void execute_command(char *cmd) +static void execute_command (const char * cmd) { - const char *argv[4] = {"/bin/sh", "-c", nullptr, nullptr}; - int i; + const char * argv[4] = {"/bin/sh", "-c", nullptr, nullptr}; argv[2] = cmd; - signal(SIGCHLD, bury_child); - if (fork() == 0) + signal (SIGCHLD, bury_child); + + if (fork () == 0) { /* We don't want this process to hog the audio device etc */ - for (i = 3; i < 255; i++) - close(i); - execv("/bin/sh", (char **)argv); + for (int i = 3; i < 255; i ++) + close (i); + execv (argv[0], (char * *) argv); } } @@ -127,15 +123,10 @@ static void execute_command(char *cmd) @cmd: command to run */ static void do_command (const char * cmd) { - char *shstring = nullptr, *temp; - gboolean playing; - Formatter *formatter; - - if (cmd && strlen(cmd) > 0) + if (cmd && strlen (cmd) > 0) { - formatter = formatter_new(); - - playing = aud_drct_get_ready(); + Formatter formatter; + bool playing = aud_drct_get_ready (); Tuple tuple; if (playing) @@ -144,151 +135,124 @@ static void do_command (const char * cmd) String ctitle = tuple.get_str (Tuple::FormattedTitle); if (ctitle) { - temp = escape_shell_chars (ctitle); - formatter_associate(formatter, 's', temp); - formatter_associate(formatter, 'n', temp); - g_free(temp); + StringBuf temp = escape_shell_chars (ctitle); + formatter.set ('s', temp); + formatter.set ('n', temp); } else { - formatter_associate(formatter, 's', ""); - formatter_associate(formatter, 'n', ""); + formatter.set ('s', ""); + formatter.set ('n', ""); } String filename = aud_drct_get_filename (); if (filename) - { - temp = escape_shell_chars (filename); - formatter_associate(formatter, 'f', temp); - g_free(temp); - } + formatter.set ('f', escape_shell_chars (filename)); else - formatter_associate(formatter, 'f', ""); + formatter.set ('f', ""); if (playing) { int pos = aud_drct_get_position (); - formatter_associate (formatter, 't', str_printf ("%02d", pos + 1)); + formatter.set ('t', str_printf ("%02d", pos + 1)); } else - formatter_associate (formatter, 't', ""); + formatter.set ('t', ""); int length = tuple.get_int (Tuple::Length); if (length > 0) - formatter_associate(formatter, 'l', int_to_str (length)); + formatter.set ('l', int_to_str (length)); else - formatter_associate(formatter, 'l', "0"); + formatter.set ('l', "0"); - formatter_associate(formatter, 'p', int_to_str (playing)); + formatter.set ('p', int_to_str (playing)); if (playing) { int brate, srate, chans; aud_drct_get_info (brate, srate, chans); - formatter_associate (formatter, 'r', int_to_str (brate)); - formatter_associate (formatter, 'F', int_to_str (srate)); - formatter_associate (formatter, 'c', int_to_str (chans)); + formatter.set ('r', int_to_str (brate)); + formatter.set ('F', int_to_str (srate)); + formatter.set ('c', int_to_str (chans)); } String artist = tuple.get_str (Tuple::Artist); if (artist) - formatter_associate(formatter, 'a', artist); + formatter.set ('a', artist); else - formatter_associate(formatter, 'a', ""); + formatter.set ('a', ""); String album = tuple.get_str (Tuple::Album); if (album) - formatter_associate(formatter, 'b', album); + formatter.set ('b', album); else - formatter_associate(formatter, 'b', ""); + formatter.set ('b', ""); String title = tuple.get_str (Tuple::Title); if (title) - formatter_associate(formatter, 'T', title); + formatter.set ('T', title); else - formatter_associate(formatter, 'T', ""); - - shstring = formatter_format(formatter, cmd); - formatter_destroy(formatter); + formatter.set ('T', ""); + StringBuf shstring = formatter.format (cmd); if (shstring) - { - execute_command(shstring); - /* FIXME: This can possibly be freed too early */ - g_free(shstring); - } + execute_command (shstring); } } -static void read_config(void) +static void songchange_playback_begin (void *, void *) { - cmd_line = aud_get_str("song_change", "cmd_line"); - cmd_line_after = aud_get_str("song_change", "cmd_line_after"); - cmd_line_end = aud_get_str("song_change", "cmd_line_end"); - cmd_line_ttc = aud_get_str("song_change", "cmd_line_ttc"); + do_command (cmd_line); } -void SongChange::cleanup () +static void songchange_playback_end (void *, void *) { - hook_dissociate("playback ready", songchange_playback_begin); - hook_dissociate("playback end", songchange_playback_end); - hook_dissociate("playlist end reached", songchange_playlist_eof); - hook_dissociate("title change", songchange_playback_ttc); - - cmd_line = String (); - cmd_line_after = String (); - cmd_line_end = String (); - cmd_line_ttc = String (); - - signal(SIGCHLD, SIG_DFL); + do_command (cmd_line_after); } -static int check_command(const char *command) +static void songchange_playback_ttc (void *, void *) { - const char *dangerous = "fns"; - const char *c; - int qu = 0; - - for (c = command; *c != '\0'; c++) - { - if (*c == '"' && (c == command || *(c - 1) != '\\')) - qu = !qu; - else if (*c == '%' && !qu && strchr(dangerous, *(c + 1))) - return -1; - } - return 0; + do_command (cmd_line_ttc); } -bool SongChange::init () +static void songchange_playlist_eof (void *, void *) { - read_config(); - - hook_associate("playback ready", songchange_playback_begin, nullptr); - hook_associate("playback end", songchange_playback_end, nullptr); - hook_associate("playlist end reached", songchange_playlist_eof, nullptr); - hook_associate("title change", songchange_playback_ttc, nullptr); - - return TRUE; + do_command (cmd_line_end); } -static void songchange_playback_begin(void *, void *) +static void read_config () { - do_command (cmd_line); + cmd_line = aud_get_str ("song_change", "cmd_line"); + cmd_line_after = aud_get_str ("song_change", "cmd_line_after"); + cmd_line_end = aud_get_str ("song_change", "cmd_line_end"); + cmd_line_ttc = aud_get_str ("song_change", "cmd_line_ttc"); } -static void songchange_playback_end(void *, void *) +bool SongChange::init () { - do_command (cmd_line_after); -} + read_config (); -static void songchange_playback_ttc(void *, void *) -{ - do_command (cmd_line_ttc); + hook_associate ("playback ready", songchange_playback_begin, nullptr); + hook_associate ("playback end", songchange_playback_end, nullptr); + hook_associate ("playlist end reached", songchange_playlist_eof, nullptr); + hook_associate ("title change", songchange_playback_ttc, nullptr); + + return true; } -static void songchange_playlist_eof(void *, void *) +void SongChange::cleanup () { - do_command (cmd_line_end); + hook_dissociate ("playback ready", songchange_playback_begin); + hook_dissociate ("playback end", songchange_playback_end); + hook_dissociate ("playlist end reached", songchange_playlist_eof); + hook_dissociate ("title change", songchange_playback_ttc); + + cmd_line = String (); + cmd_line_after = String (); + cmd_line_end = String (); + cmd_line_ttc = String (); + + signal (SIGCHLD, SIG_DFL); } typedef struct { @@ -300,98 +264,41 @@ typedef struct { static SongChangeConfig config; -static void edit_cb() -{ - if (check_command(config.cmd) < 0 || check_command(config.cmd_after) < 0 || - check_command(config.cmd_end) < 0 || check_command(config.cmd_ttc) < 0) - { - gtk_widget_show(cmd_warn_img); - gtk_widget_show(cmd_warn_label); - } - else - { - gtk_widget_hide(cmd_warn_img); - gtk_widget_hide(cmd_warn_label); - } -} - -static void configure_ok_cb() -{ - aud_set_str("song_change", "cmd_line", config.cmd); - aud_set_str("song_change", "cmd_line_after", config.cmd_after); - aud_set_str("song_change", "cmd_line_end", config.cmd_end); - aud_set_str("song_change", "cmd_line_ttc", config.cmd_ttc); - - cmd_line = config.cmd; - cmd_line_after = config.cmd_after; - cmd_line_end = config.cmd_end; - cmd_line_ttc = config.cmd_ttc; -} - -/* static GtkWidget * custom_warning (void) */ -static void * custom_warning (void) -{ - GtkWidget *bbox_hbox; - char * temp; - - bbox_hbox = gtk_hbox_new (FALSE, 6); - - cmd_warn_img = gtk_image_new_from_icon_name("dialog-warning", GTK_ICON_SIZE_MENU); - gtk_box_pack_start(GTK_BOX(bbox_hbox), cmd_warn_img, FALSE, FALSE, 0); - - temp = g_strdup_printf(_("<span size='small'>Parameters passed to the shell should be encapsulated in quotes. Doing otherwise is a security risk.</span>")); - cmd_warn_label = gtk_label_new(temp); - gtk_label_set_markup(GTK_LABEL(cmd_warn_label), temp); - gtk_label_set_line_wrap(GTK_LABEL(cmd_warn_label), TRUE); - gtk_box_pack_start(GTK_BOX(bbox_hbox), cmd_warn_label, FALSE, FALSE, 0); - g_free(temp); - - gtk_widget_set_no_show_all(cmd_warn_img, TRUE); - gtk_widget_set_no_show_all(cmd_warn_label, TRUE); - - edit_cb(); - - return bbox_hbox; -} - const PreferencesWidget SongChange::widgets[] = { WidgetLabel (N_("<b>Commands</b>")), WidgetLabel (N_("Command to run when starting a new song:")), - WidgetEntry (0, WidgetString (config.cmd, edit_cb)), - WidgetSeparator ({true}), + WidgetEntry (0, WidgetString (config.cmd)), WidgetLabel (N_("Command to run at the end of a song:")), - WidgetEntry (0, WidgetString (config.cmd_after, edit_cb)), - WidgetSeparator ({true}), + WidgetEntry (0, WidgetString (config.cmd_after)), WidgetLabel (N_("Command to run at the end of the playlist:")), - WidgetEntry (0, WidgetString (config.cmd_end, edit_cb)), - WidgetSeparator ({true}), + WidgetEntry (0, WidgetString (config.cmd_end)), WidgetLabel (N_("Command to run when song title changes (for network streams):")), - WidgetEntry (0, WidgetString (config.cmd_ttc, edit_cb)), - WidgetSeparator ({true}), + WidgetEntry (0, WidgetString (config.cmd_ttc)), - WidgetLabel (N_("You can use the following format strings which " - "will be substituted before calling the command " - "(not all are useful for the end-of-playlist command):\n\n" - "%F: Frequency (in hertz)\n" + WidgetLabel (N_("You can use the following format codes, which will be " + "replaced before running the command (not all are useful " + "for the end-of-playlist command):")), + WidgetLabel (N_("%a: Artist\n" + "%b: Album\n" "%c: Number of channels\n" "%f: File name (full path)\n" - "%l: Length (in milliseconds)\n" - "%n or %s: Song name\n" - "%r: Rate (in bits per second)\n" - "%t: Playlist position (%02d)\n" + "%F: Frequency (Hertz)\n" + "%l: Length (milliseconds)\n" + "%n or %s: Formatted title (see playlist settings)\n" "%p: Currently playing (1 or 0)\n" - "%a: Artist\n" - "%b: Album\n" - "%T: Track title")), - - WidgetCustomGTK (custom_warning) + "%r: Rate (bits per second)\n" + "%t: Playlist position\n" + "%T: Title (unformatted)")), + WidgetLabel (N_("Parameters passed to the shell should be enclosed in " + "quotation marks. Unquoted parameters may lead to " + "unexpected results.")) }; -static void configure_init(void) +static void configure_init () { config.cmd = cmd_line; config.cmd_after = cmd_line_after; @@ -399,7 +306,20 @@ static void configure_init(void) config.cmd_ttc = cmd_line_ttc; } -static void configure_cleanup(void) +static void configure_ok_cb () +{ + aud_set_str ("song_change", "cmd_line", config.cmd); + aud_set_str ("song_change", "cmd_line_after", config.cmd_after); + aud_set_str ("song_change", "cmd_line_end", config.cmd_end); + aud_set_str ("song_change", "cmd_line_ttc", config.cmd_ttc); + + cmd_line = config.cmd; + cmd_line_after = config.cmd_after; + cmd_line_end = config.cmd_end; + cmd_line_ttc = config.cmd_ttc; +} + +static void configure_cleanup () { config.cmd = String (); config.cmd_after = String (); diff --git a/src/statusicon-qt/Makefile b/src/statusicon-qt/Makefile new file mode 100644 index 0000000..e420c86 --- /dev/null +++ b/src/statusicon-qt/Makefile @@ -0,0 +1,13 @@ +PLUGIN = statusicon-qt${PLUGIN_SUFFIX} + +SRCS = statusicon.cc + +include ../../buildsys.mk +include ../../extra.mk + +plugindir := ${plugindir}/${GENERAL_PLUGIN_DIR} + +LD = ${CXX} +CFLAGS += ${PLUGIN_CFLAGS} +CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../.. ${QT_CFLAGS} +LIBS += ${QT_LIBS} -laudqt diff --git a/src/statusicon-qt/statusicon.cc b/src/statusicon-qt/statusicon.cc new file mode 100644 index 0000000..d1218a9 --- /dev/null +++ b/src/statusicon-qt/statusicon.cc @@ -0,0 +1,192 @@ +/* + * statusicon.cc + * Copyright 2015 Eugene Paskevich + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions, and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions, and the following disclaimer in the documentation + * provided with the distribution. + * + * This software is provided "as is" and without any warranty, express or + * implied. In no event shall the authors be liable for any damages arising from + * the use of this software. + */ + +#define AUD_PLUGIN_QT_ONLY +#include <libaudcore/i18n.h> +#include <libaudcore/drct.h> +#include <libaudcore/hook.h> +#include <libaudcore/plugin.h> +#include <libaudcore/runtime.h> +#include <libaudcore/interface.h> +#include <libaudcore/preferences.h> + +#include <libaudqt/menu.h> + +#include <QApplication> +#include <QMenu> +#include <QSystemTrayIcon> + +class StatusIcon : public GeneralPlugin { +public: + static const char about[]; + static const char * const defaults[]; + static const PreferencesWidget widgets[]; + static const PluginPreferences prefs; + static const audqt::MenuItem items[]; + + static constexpr PluginInfo info = { + N_("Status Icon"), + PACKAGE, + about, + & prefs + }; + + constexpr StatusIcon () : GeneralPlugin (info, false) {} + + bool init (); + void cleanup (); + + static void window_closed (void * data, void * user_data); + static void activate (QSystemTrayIcon::ActivationReason); + static void open_files (); + static void toggle_aud_ui (); + static void update_menu (); +}; + +EXPORT StatusIcon aud_plugin_instance; + +const char StatusIcon::about[] = + N_("Status Icon Plugin (partial port for Qt interface)\n\n" + "Copyright 2005-2007 Giacomo Lozito <james@develia.org>\n" + "Copyright 2010 Michał Lipski <tallica@o2.pl>\n" + "Copyright 2015 Eugene Paskevich <eugene@raptor.kiev.ua>\n\n" + "This plugin provides a status icon, placed in\n" + "the system tray area of the window manager."); + +const char * const StatusIcon::defaults[] = { + "close_to_tray", "FALSE", + nullptr +}; + +const PreferencesWidget StatusIcon::widgets[] = { + WidgetCheck (N_("Close to the system tray"), WidgetBool ("statusicon-qt", "close_to_tray")) +}; + +const PluginPreferences StatusIcon::prefs = {{widgets}}; + +const audqt::MenuItem StatusIcon::items[] = +{ + audqt::MenuCommand ({N_("_Hide"), "window-close"}, StatusIcon::toggle_aud_ui), + audqt::MenuCommand ({N_("_Restore"), "window-new"}, StatusIcon::toggle_aud_ui), + audqt::MenuSep (), + audqt::MenuCommand ({N_("_Open Files ..."), "document-open"}, StatusIcon::open_files), + audqt::MenuCommand ({N_("Pre_vious"), "media-skip-backward"}, aud_drct_pl_prev), + audqt::MenuCommand ({N_("_Play"), "media-playback-start"}, aud_drct_play), + audqt::MenuCommand ({N_("Paus_e"), "media-playback-pause"}, aud_drct_pause), + audqt::MenuCommand ({N_("_Stop"), "media-playback-stop"}, aud_drct_stop), + audqt::MenuCommand ({N_("_Next"), "media-skip-forward"}, aud_drct_pl_next), + audqt::MenuSep (), + audqt::MenuCommand ({N_("Se_ttings ..."), "preferences-system"}, audqt::prefswin_show), + audqt::MenuCommand ({N_("_Quit"), "application-exit"}, aud_quit), +}; + +static QSystemTrayIcon * tray = nullptr; +static QMenu * menu = nullptr; + +bool StatusIcon::init () +{ + aud_config_set_defaults ("statusicon-qt", defaults); + + audqt::init (); + + tray = new QSystemTrayIcon (qApp->windowIcon ()); + QObject::connect (tray, & QSystemTrayIcon::activated, activate); + menu = audqt::menu_build (items); + // Very dirty hack to get along with KDE5 SNI implementation + // which adds Quit action without any permission. + // See below in activate(). + menu->actions ().last ()->setVisible (false); + tray->setContextMenu (menu); + QObject::connect (menu, & QMenu::aboutToShow, update_menu); + tray->show (); + + hook_associate ("window close", window_closed, nullptr); + + return true; +} + +void StatusIcon::cleanup () +{ + hook_dissociate ("window close", window_closed); + + /* Prevent accidentally hiding the interface by disabling + * the plugin while Audacious is closed to the tray. */ + PluginHandle * p = aud_plugin_by_header (& aud_plugin_instance); + if (! aud_plugin_get_enabled (p) && ! aud_get_headless_mode () && ! aud_ui_is_shown ()) + aud_ui_show (true); + + delete tray; + tray = nullptr; + delete menu; + menu = nullptr; + + audqt::cleanup (); +} + +void StatusIcon::window_closed (void * data, void * user_data) +{ + bool * handled = (bool *) data; + + if (aud_get_bool ("statusicon-qt", "close_to_tray") && tray->isVisible ()) + { + * handled = true; + aud_ui_show (false); + } +} + +void StatusIcon::activate(QSystemTrayIcon::ActivationReason reason) +{ + switch (reason) + { + case QSystemTrayIcon::Trigger: + toggle_aud_ui (); + break; + + case QSystemTrayIcon::Context: + // It is expected that only KDE5 SNI implementation blocks this activation signal. + // So getting it means we aren't in KDE and should show the Quit action. + menu->actions ().last ()->setVisible (true); + break; + + case QSystemTrayIcon::MiddleClick: + aud_drct_pause (); + break; + + default: + break; + } +} + +void StatusIcon::open_files () +{ + audqt::fileopener_show (audqt::FileMode::Open); +} + +void StatusIcon::toggle_aud_ui () +{ + aud_ui_show (! aud_ui_is_shown ()); +} + +void StatusIcon::update_menu () +{ + QList< QAction *> acts = menu->actions (); + + acts.at (0)->setVisible (aud_ui_is_shown ()); + acts.at (1)->setVisible (! aud_ui_is_shown ()); +} diff --git a/src/statusicon/statusicon.cc b/src/statusicon/statusicon.cc index 5c5f387..152111f 100644 --- a/src/statusicon/statusicon.cc +++ b/src/statusicon/statusicon.cc @@ -22,6 +22,7 @@ #include <gdk/gdk.h> #include <gtk/gtk.h> +#define AUD_PLUGIN_GLIB_ONLY #include <libaudcore/audstrings.h> #include <libaudcore/drct.h> #include <libaudcore/i18n.h> @@ -72,7 +73,7 @@ static void si_menu_show (int x, int y, unsigned button, uint32_t time, void *); static void si_popup_hide (void * icon); const char * const StatusIcon::defaults[] = { - "scroll_action", "0", /* SI_CFG_SCROLL_ACTION_VOLUME */ + "scroll_action", aud::numeric_string<SI_CFG_SCROLL_ACTION_VOLUME>::str, "volume_delta", "5", "disable_popup", "FALSE", "close_to_tray", "FALSE", @@ -353,9 +354,6 @@ static void si_enable (bool enable) bool StatusIcon::init () { - if (aud_get_mainloop_type () != MainloopType::GLib) - return false; - aud_config_set_defaults ("statusicon", defaults); audgui_init (); si_enable (true); diff --git a/src/vorbis/vcedit.cc b/src/vorbis/vcedit.cc index 6b650ae..188a4cb 100644 --- a/src/vorbis/vcedit.cc +++ b/src/vorbis/vcedit.cc @@ -18,7 +18,7 @@ #define CHUNKSIZE 4096 vcedit_state * -vcedit_new_state(void) +vcedit_new_state() { return g_new0(vcedit_state, 1); } diff --git a/src/vorbis/vcedit.h b/src/vorbis/vcedit.h index a262395..5473b84 100644 --- a/src/vorbis/vcedit.h +++ b/src/vorbis/vcedit.h @@ -12,7 +12,7 @@ #include <ogg/ogg.h> #include <vorbis/codec.h> -#include <libaudcore/plugin.h> +#include <libaudcore/vfs.h> typedef struct { ogg_sync_state *oy; @@ -34,7 +34,7 @@ typedef struct { int eosin; } vcedit_state; -extern vcedit_state *vcedit_new_state(void); +extern vcedit_state *vcedit_new_state(); extern void vcedit_clear(vcedit_state *state); extern vorbis_comment *vcedit_comments(vcedit_state *state); extern int vcedit_open(vcedit_state *state, VFSFile &in); diff --git a/src/vorbis/vcupdate.cc b/src/vorbis/vcupdate.cc index 096ff10..bb4d62e 100644 --- a/src/vorbis/vcupdate.cc +++ b/src/vorbis/vcupdate.cc @@ -33,7 +33,6 @@ #include <libaudcore/audstrings.h> #include <libaudcore/i18n.h> #include <libaudcore/multihash.h> -#include <libaudcore/plugin.h> #include <libaudcore/runtime.h> #include "vorbis.h" @@ -168,7 +167,7 @@ FAILED: bool write_and_pivot_files (vcedit_state * state) { char * temp; - GError * error; + GError * error = nullptr; int handle = g_file_open_tmp (nullptr, & temp, & error); if (handle < 0) diff --git a/src/vorbis/vorbis.cc b/src/vorbis/vorbis.cc index 531ec95..71c86bb 100644 --- a/src/vorbis/vorbis.cc +++ b/src/vorbis/vorbis.cc @@ -4,7 +4,7 @@ * Copyright (C) 2007 William Pitcock <nenolod@sacredspiral.co.uk> * Copyright (C) 2008 Cristi Măgherușan <majeru@gentoo.ro> * Copyright (C) 2008 Eugene Zagidullin <e.asphyx@gmail.com> - * Copyright (C) 2009-2011 Audacious Developers + * Copyright (C) 2009-2015 Audacious Developers * * ReplayGain processing Copyright (C) 2002 Gian-Carlo Pascutto <gcp@sjeng.org> * @@ -37,13 +37,14 @@ #define WANT_AUD_BSWAP #define WANT_VFS_STDIO_COMPAT #include <libaudcore/audstrings.h> -#include <libaudcore/plugin.h> #include <libaudcore/runtime.h> #include "vorbis.h" EXPORT VorbisPlugin aud_plugin_instance; +static Index<char> read_image_from_comment (const char * filename, vorbis_comment * comment); + static size_t ovcb_read (void * buffer, size_t size, size_t count, void * file) { return ((VFSFile *) file)->fread (buffer, size, count); @@ -130,118 +131,64 @@ set_tuple_str(Tuple &tuple, Tuple::Field field, tuple.set_str (field, vorbis_comment_query (comment, key, 0)); } -static Tuple -get_tuple_for_vorbisfile(OggVorbis_File * vorbisfile, const char *filename, bool stream) +static void read_comment (vorbis_comment * comment, Tuple & tuple) { - Tuple tuple; - int length = -1; - vorbis_comment *comment = nullptr; - - tuple.set_filename(filename); - - if (! stream) - length = ov_time_total (vorbisfile, -1) * 1000; - - /* associate with tuple */ - tuple.set_int (Tuple::Length, length); - - if ((comment = ov_comment(vorbisfile, -1)) != nullptr) { - char *tmps; - set_tuple_str(tuple, Tuple::Title, comment, "title"); - set_tuple_str(tuple, Tuple::Artist, comment, "artist"); - set_tuple_str(tuple, Tuple::Album, comment, "album"); - set_tuple_str(tuple, Tuple::Genre, comment, "genre"); - set_tuple_str(tuple, Tuple::Comment, comment, "comment"); - - if ((tmps = vorbis_comment_query(comment, "tracknumber", 0)) != nullptr) - tuple.set_int (Tuple::Track, atoi(tmps)); - - if ((tmps = vorbis_comment_query (comment, "date", 0)) != nullptr) - tuple.set_int (Tuple::Year, atoi (tmps)); - } - - vorbis_info * info = ov_info (vorbisfile, -1); - tuple.set_format ("Ogg Vorbis", info->channels, info->rate, info->bitrate_nominal / 1000); - - tuple.set_str (Tuple::MIMEType, "application/ogg"); - - return tuple; -} - -static float atof_no_locale (const char * string) -{ - float result = 0; - bool negative = false; - - if (* string == '+') - string ++; - else if (* string == '-') - { - negative = true; - string ++; - } - - while (* string >= '0' && * string <= '9') - result = 10 * result + (* string ++ - '0'); - - if (* string == '.') - { - float place = 0.1; - - string ++; - - while (* string >= '0' && * string <= '9') - { - result += (* string ++ - '0') * place; - place *= 0.1; - } - } - - return negative ? -result : result; + const char * tmps; + + set_tuple_str (tuple, Tuple::Title, comment, "title"); + set_tuple_str (tuple, Tuple::Artist, comment, "artist"); + set_tuple_str (tuple, Tuple::Album, comment, "album"); + set_tuple_str (tuple, Tuple::Genre, comment, "genre"); + set_tuple_str (tuple, Tuple::Comment, comment, "comment"); + + if ((tmps = vorbis_comment_query (comment, "tracknumber", 0))) + tuple.set_int (Tuple::Track, atoi (tmps)); + if ((tmps = vorbis_comment_query (comment, "date", 0))) + tuple.set_int (Tuple::Year, atoi (tmps)); } /* try to detect when metadata has changed */ -static bool vorbis_fetch_tuple (OggVorbis_File * vf, const char * filename, bool stream, Tuple & tuple) +static bool update_tuple (OggVorbis_File * vf, Tuple & tuple) { - String old_title = tuple.get_str (Tuple::Title); vorbis_comment * comment = ov_comment (vf, -1); - const char * new_title = comment ? vorbis_comment_query (comment, "title", 0) : nullptr; + if (! comment) + return false; + + String old_title = tuple.get_str (Tuple::Title); + const char * new_title = vorbis_comment_query (comment, "title", 0); if (! new_title || (old_title && ! strcmp (old_title, new_title))) return false; - tuple = get_tuple_for_vorbisfile (vf, filename, stream); + read_comment (comment, tuple); return true; } -static bool vorbis_fetch_replaygain (OggVorbis_File * vf, ReplayGainInfo * rg_info) +static bool update_replay_gain (OggVorbis_File * vf, ReplayGainInfo * rg_info) { - vorbis_comment *comment; - char *rg_gain, *rg_peak; + const char *rg_gain, *rg_peak; - if (vf == nullptr || rg_info == nullptr || (comment = ov_comment(vf, -1)) == nullptr) - { - AUDDBG ("No replay gain info.\n"); + vorbis_comment * comment = ov_comment (vf, -1); + if (! comment) return false; - } rg_gain = vorbis_comment_query(comment, "replaygain_album_gain", 0); if (!rg_gain) rg_gain = vorbis_comment_query(comment, "rg_audiophile", 0); /* Old */ - rg_info->album_gain = (rg_gain != nullptr) ? atof_no_locale (rg_gain) : 0.0; + rg_info->album_gain = (rg_gain != nullptr) ? str_to_double (rg_gain) : 0.0; AUDDBG ("Album gain: %s (%f)\n", rg_gain, rg_info->album_gain); rg_gain = vorbis_comment_query(comment, "replaygain_track_gain", 0); if (!rg_gain) rg_gain = vorbis_comment_query(comment, "rg_radio", 0); /* Old */ - rg_info->track_gain = (rg_gain != nullptr) ? atof_no_locale (rg_gain) : 0.0; + rg_info->track_gain = (rg_gain != nullptr) ? str_to_double (rg_gain) : 0.0; AUDDBG ("Track gain: %s (%f)\n", rg_gain, rg_info->track_gain); rg_peak = vorbis_comment_query(comment, "replaygain_album_peak", 0); - rg_info->album_peak = rg_peak != nullptr ? atof_no_locale (rg_peak) : 0.0; + rg_info->album_peak = rg_peak != nullptr ? str_to_double (rg_peak) : 0.0; AUDDBG ("Album peak: %s (%f)\n", rg_peak, rg_info->album_peak); rg_peak = vorbis_comment_query(comment, "replaygain_track_peak", 0); if (!rg_peak) rg_peak = vorbis_comment_query(comment, "rg_peak", 0); /* Old */ - rg_info->track_peak = rg_peak != nullptr ? atof_no_locale (rg_peak) : 0.0; + rg_info->track_peak = rg_peak != nullptr ? str_to_double (rg_peak) : 0.0; AUDDBG ("Track peak: %s (%f)\n", rg_peak, rg_info->track_peak); return true; @@ -267,7 +214,7 @@ bool VorbisPlugin::play (const char * filename, VFSFile & file) vorbis_info *vi; OggVorbis_File vf; int last_section = -1; - Tuple tuple; + Tuple tuple = get_playback_tuple (); ReplayGainInfo rg_info; float pcmout[PCM_BUFSIZE*sizeof(float)], **pcm; int bytes, channels, samplerate, br; @@ -292,10 +239,10 @@ bool VorbisPlugin::play (const char * filename, VFSFile & file) set_stream_bitrate (br); - if (vorbis_fetch_tuple (& vf, filename, stream, tuple)) + if (update_tuple (& vf, tuple)) set_playback_tuple (tuple.ref ()); - if (vorbis_fetch_replaygain (& vf, & rg_info)) + if (update_replay_gain (& vf, & rg_info)) set_replay_gain (rg_info); open_audio (FMT_FLOAT, samplerate, channels); @@ -328,7 +275,7 @@ bool VorbisPlugin::play (const char * filename, VFSFile & file) bytes = vorbis_interleave_buffer (pcm, bytes, channels, pcmout); - if (vorbis_fetch_tuple (& vf, filename, stream, tuple)) + if (update_tuple (& vf, tuple)) set_playback_tuple (tuple.ref ()); if (current_section != last_section) @@ -345,7 +292,7 @@ bool VorbisPlugin::play (const char * filename, VFSFile & file) samplerate = vi->rate; channels = vi->channels; - if (vorbis_fetch_replaygain (& vf, & rg_info)) + if (update_replay_gain (& vf, & rg_info)) set_replay_gain (rg_info); open_audio (FMT_FLOAT, vi->rate, vi->channels); @@ -367,9 +314,9 @@ play_cleanup: return ! error; } -Tuple VorbisPlugin::read_tuple (const char * filename, VFSFile & file) +bool VorbisPlugin::read_tag (const char * filename, VFSFile & file, Tuple * tuple, Index<char> * image) { - OggVorbis_File vfile; /* avoid thread interaction */ + OggVorbis_File vfile; bool stream = (file.fsize () < 0); @@ -380,29 +327,33 @@ Tuple VorbisPlugin::read_tuple (const char * filename, VFSFile & file) */ if (ov_open_callbacks (& file, & vfile, nullptr, 0, stream ? vorbis_callbacks_stream : vorbis_callbacks) < 0) - return Tuple (); + return false; - Tuple tuple = get_tuple_for_vorbisfile(&vfile, filename, stream); - ov_clear(&vfile); - return tuple; -} + vorbis_comment * comment = ov_comment (& vfile, -1); -Index<char> VorbisPlugin::read_image (const char * filename, VFSFile & file) -{ - Index<char> data; + if (tuple) + { + vorbis_info * info = ov_info (& vfile, -1); + tuple->set_format ("Ogg Vorbis", info->channels, info->rate, info->bitrate_nominal / 1000); + tuple->set_str (Tuple::MIMEType, "application/ogg"); - OggVorbis_File vfile; + if (! stream) + tuple->set_int (Tuple::Length, ov_time_total (& vfile, -1) * 1000); - bool stream = (file.fsize () < 0); + if (comment) + read_comment (comment, * tuple); + } - if (ov_open_callbacks (& file, & vfile, nullptr, 0, stream ? - vorbis_callbacks_stream : vorbis_callbacks) < 0) - return data; + if (image && comment) + * image = read_image_from_comment (filename, comment); - vorbis_comment * comment = ov_comment (& vfile, -1); - if (! comment) - goto ERR; + ov_clear (& vfile); + return true; +} +static Index<char> read_image_from_comment (const char * filename, vorbis_comment * comment) +{ + Index<char> data; const char * s; if ((s = vorbis_comment_query (comment, "METADATA_BLOCK_PICTURE", 0))) @@ -429,7 +380,6 @@ Index<char> VorbisPlugin::read_image (const char * filename, VFSFile & file) data.insert ((char *) data2 + 8 + mime_length + 4 + desc_length + 20, 0, length); g_free (data2); - ov_clear (& vfile); return data; PARSE_ERR: @@ -442,22 +392,15 @@ Index<char> VorbisPlugin::read_image (const char * filename, VFSFile & file) size_t length2; void * data2 = g_base64_decode (s, & length2); - if (! data2 || ! length2) - { + if (data2 && length2) + data.insert ((const char *) data2, 0, length2); + else AUDERR ("Error parsing COVERART in %s.\n", filename); - g_free (data2); - goto ERR; - } - - data.insert ((const char *) data2, 0, length2); g_free (data2); - ov_clear (& vfile); return data; } -ERR: - ov_clear (& vfile); return data; } diff --git a/src/vorbis/vorbis.h b/src/vorbis/vorbis.h index 28ab572..e5684f0 100644 --- a/src/vorbis/vorbis.h +++ b/src/vorbis/vorbis.h @@ -28,8 +28,7 @@ public: constexpr VorbisPlugin () : InputPlugin (info, iinfo) {} bool is_our_file (const char * filename, VFSFile & file); - Tuple read_tuple (const char * filename, VFSFile & file); - Index<char> read_image (const char * filename, VFSFile & file); + bool read_tag (const char * filename, VFSFile & file, Tuple * tuple, Index<char> * image); bool write_tuple (const char * filename, VFSFile & file, const Tuple & tuple); bool play (const char * filename, VFSFile & file); }; diff --git a/src/vtx/Makefile b/src/vtx/Makefile index 7fbab2f..be4de00 100644 --- a/src/vtx/Makefile +++ b/src/vtx/Makefile @@ -14,5 +14,9 @@ plugindir := ${plugindir}/${INPUT_PLUGIN_DIR} LD = ${CXX} CFLAGS += ${PLUGIN_CFLAGS} -CPPFLAGS += ${PLUGIN_CPPFLAGS} ${GTK_CFLAGS} ${GLIB_CFLAGS} -I../.. -I. -LIBS += ${GTK_LIBS} ${GLIB_LIBS} -laudgui +CPPFLAGS += ${PLUGIN_CPPFLAGS} -I../.. + +ifeq ($(USE_GTK),yes) +CPPFLAGS += ${GTK_CFLAGS} +LIBS += ${GTK_LIBS} -laudgui +endif diff --git a/src/vtx/ayemu_vtxfile.h b/src/vtx/ayemu_vtxfile.h index 227945d..c83380f 100644 --- a/src/vtx/ayemu_vtxfile.h +++ b/src/vtx/ayemu_vtxfile.h @@ -2,7 +2,7 @@ #define _AYEMU_vtxfile_h #include <inttypes.h> -#include <libaudcore/plugin.h> +#include <libaudcore/vfs.h> #include "ayemu_8912.h" /* The following constants and data structure comes from diff --git a/src/vtx/info.cc b/src/vtx/info.cc index 8401982..7873346 100644 --- a/src/vtx/info.cc +++ b/src/vtx/info.cc @@ -1,6 +1,8 @@ #include "ayemu.h" #include "vtx.h" +#ifdef USE_GTK + #include <libaudcore/audstrings.h> #include <libaudcore/i18n.h> #include <libaudcore/runtime.h> @@ -36,3 +38,5 @@ void vtx_file_info(const char *filename, VFSFile &file) audgui_simple_message (& box, GTK_MESSAGE_INFO, head, body); } } + +#endif // USE_GTK diff --git a/src/vtx/lh5dec.cc b/src/vtx/lh5dec.cc index b9cebc0..42a31b4 100644 --- a/src/vtx/lh5dec.cc +++ b/src/vtx/lh5dec.cc @@ -164,7 +164,7 @@ static void read_pt_len(int nn, int nbit, int i_special) } } -static void read_c_len(void) +static void read_c_len() { int i, c, n; unsigned short mask; @@ -200,7 +200,7 @@ static void read_c_len(void) } -static unsigned short decode_c(void) +static unsigned short decode_c() { unsigned short j, mask; @@ -225,7 +225,7 @@ static unsigned short decode_c(void) } -static unsigned short decode_p(void) +static unsigned short decode_p() { unsigned short j, mask; diff --git a/src/vtx/vtx.cc b/src/vtx/vtx.cc index d670945..038521b 100644 --- a/src/vtx/vtx.cc +++ b/src/vtx/vtx.cc @@ -49,8 +49,10 @@ public: Tuple read_tuple(const char *filename, VFSFile &file); bool play(const char *filename, VFSFile &file); +#ifdef USE_GTK bool file_info_box(const char *filename, VFSFile &file) { vtx_file_info(filename, file); return true; } +#endif }; EXPORT VTXPlugin aud_plugin_instance; diff --git a/src/vtx/vtxfile.cc b/src/vtx/vtxfile.cc index ccf95d5..83c3801 100644 --- a/src/vtx/vtxfile.cc +++ b/src/vtx/vtxfile.cc @@ -5,7 +5,7 @@ #include <inttypes.h> #include <libaudcore/audstrings.h> -#include <libaudcore/plugin.h> +#include <libaudcore/vfs.h> #include <libaudcore/runtime.h> #include "ayemu.h" diff --git a/src/wavpack/wavpack.cc b/src/wavpack/wavpack.cc index f726702..4e35df5 100644 --- a/src/wavpack/wavpack.cc +++ b/src/wavpack/wavpack.cc @@ -240,7 +240,7 @@ Tuple WavpackPlugin::read_tuple (const char * filename, VFSFile & file) WavpackCloseFile(ctx); if (! file.fseek (0, VFS_SEEK_SET)) - audtag::tuple_read (tuple, file); + audtag::read_tag (file, & tuple, nullptr); AUDDBG("returning tuple for file %s\n", file.filename ()); return tuple; diff --git a/src/xsf/desmume/NDSSystem.h b/src/xsf/desmume/NDSSystem.h index 2417f61..9a7d012 100644 --- a/src/xsf/desmume/NDSSystem.h +++ b/src/xsf/desmume/NDSSystem.h @@ -224,9 +224,11 @@ NDS_exec(s32 nb, BOOL force); static INLINE void NDS_ARM7VBlankInt(void) { if(T1ReadWord(MMU.ARM7_REG, 4) & 0x8) + { MMU.reg_IF[1] |= 1;// & (MMU.reg_IME[1]);// (MMU.reg_IE[1] & 1); NDS_ARM7.wIRQ = true; //execute = false; + } } static INLINE void NDS_swapScreen(void) diff --git a/src/xsf/plugin.cc b/src/xsf/plugin.cc index 3f38f85..ae116b8 100644 --- a/src/xsf/plugin.cc +++ b/src/xsf/plugin.cc @@ -75,7 +75,7 @@ static String dirpath; const char* const XSFPlugin::defaults[] = { "ignore_length", "FALSE", - NULL + nullptr }; bool XSFPlugin::init() diff --git a/src/xspf/xspf.cc b/src/xspf/xspf.cc index 67b71b7..5072774 100644 --- a/src/xspf/xspf.cc +++ b/src/xspf/xspf.cc @@ -326,7 +326,7 @@ static void xspf_add_node(xmlNodePtr node, Tuple::ValueType type, tmp = xmlNewNode(nullptr, (xmlChar *) xspfName); switch (type) { - case Tuple::String:; + case Tuple::String: char * subst; if (is_valid_string (strVal, & subst)) xmlAddChild (tmp, xmlNewText ((xmlChar *) strVal)); |