summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMateusz Łukasik <mati75@linuxmint.pl>2016-02-05 21:48:39 +0100
committerMateusz Łukasik <mati75@linuxmint.pl>2016-02-05 21:48:39 +0100
commit26646e3484d7d03d68003553d6c98ecddf2fa082 (patch)
tree1e80b6641ecb9b8ae702c524dc30fb423bad15fc /src
parent35d79008b7047120cc1f3fde00e7532ddc432755 (diff)
Imported Upstream version 3.7.1
Diffstat (limited to 'src')
-rw-r--r--src/adplug/Makefile12
-rw-r--r--src/adplug/adplug-xmms.cc48
-rw-r--r--src/adplug/binio/binfile.cc247
-rw-r--r--src/adplug/binio/binfile.h110
-rw-r--r--src/adplug/binio/binio.cc298
-rw-r--r--src/adplug/binio/binio.h137
-rw-r--r--src/adplug/binio/binio_virtual.h51
-rw-r--r--src/adplug/binio/binstr.cc114
-rw-r--r--src/adplug/binio/binstr.h66
-rw-r--r--src/adplug/core/a2m.cc769
-rw-r--r--src/adplug/core/a2m.h87
-rw-r--r--src/adplug/core/adl.cc1891
-rw-r--r--src/adplug/core/adl.h4
-rw-r--r--src/adplug/core/adlibemu.cc541
-rw-r--r--src/adplug/core/adlibemu.h6
-rw-r--r--src/adplug/core/adplug.cc244
-rw-r--r--src/adplug/core/adplug.h15
-rw-r--r--src/adplug/core/adtrack.cc170
-rw-r--r--src/adplug/core/adtrack.h40
-rw-r--r--src/adplug/core/amd.cc166
-rw-r--r--src/adplug/core/amd.h38
-rw-r--r--src/adplug/core/bam.cc317
-rw-r--r--src/adplug/core/bam.h48
-rw-r--r--src/adplug/core/binio_virtual.h90
-rw-r--r--src/adplug/core/bmf.cc619
-rw-r--r--src/adplug/core/bmf.h8
-rw-r--r--src/adplug/core/cff.cc616
-rw-r--r--src/adplug/core/cff.h110
-rw-r--r--src/adplug/core/cmf.cc1179
-rw-r--r--src/adplug/core/cmf.h130
-rw-r--r--src/adplug/core/d00.cc606
-rw-r--r--src/adplug/core/d00.h126
-rw-r--r--src/adplug/core/database.cc430
-rw-r--r--src/adplug/core/database.h61
-rw-r--r--src/adplug/core/debug.cc2
-rw-r--r--src/adplug/core/debug.h2
-rw-r--r--src/adplug/core/dfm.cc148
-rw-r--r--src/adplug/core/dfm.h42
-rw-r--r--src/adplug/core/diskopl.h52
-rw-r--r--src/adplug/core/dmo.cc473
-rw-r--r--src/adplug/core/dmo.h8
-rw-r--r--src/adplug/core/dro.cc126
-rw-r--r--src/adplug/core/dro.h10
-rw-r--r--src/adplug/core/dro2.cc174
-rw-r--r--src/adplug/core/dro2.h72
-rw-r--r--src/adplug/core/dtm.cc375
-rw-r--r--src/adplug/core/dtm.h68
-rw-r--r--src/adplug/core/emuopl.cc119
-rw-r--r--src/adplug/core/emuopl.h12
-rw-r--r--src/adplug/core/flash.cc197
-rw-r--r--src/adplug/core/flash.h12
-rw-r--r--src/adplug/core/fmc.cc290
-rw-r--r--src/adplug/core/fmc.h130
-rw-r--r--src/adplug/core/fmopl.cc2007
-rw-r--r--src/adplug/core/fmopl.h184
-rw-r--r--src/adplug/core/fprovide.cc46
-rw-r--r--src/adplug/core/fprovide.h31
-rw-r--r--src/adplug/core/hsc.cc344
-rw-r--r--src/adplug/core/hsc.h36
-rw-r--r--src/adplug/core/hsp.cc58
-rw-r--r--src/adplug/core/hsp.h14
-rw-r--r--src/adplug/core/hybrid.cc230
-rw-r--r--src/adplug/core/hybrid.h6
-rw-r--r--src/adplug/core/hyp.cc54
-rw-r--r--src/adplug/core/hyp.h20
-rw-r--r--src/adplug/core/imf.cc178
-rw-r--r--src/adplug/core/imf.h60
-rw-r--r--src/adplug/core/jbm.cc79
-rw-r--r--src/adplug/core/jbm.h8
-rw-r--r--src/adplug/core/kemuopl.h6
-rw-r--r--src/adplug/core/ksm.cc538
-rw-r--r--src/adplug/core/ksm.h58
-rw-r--r--src/adplug/core/lds.cc857
-rw-r--r--src/adplug/core/lds.h52
-rw-r--r--src/adplug/core/mad.cc109
-rw-r--r--src/adplug/core/mad.h28
-rw-r--r--src/adplug/core/mid.cc1827
-rw-r--r--src/adplug/core/mid.h10
-rw-r--r--src/adplug/core/mididata.h10
-rw-r--r--src/adplug/core/mkj.cc201
-rw-r--r--src/adplug/core/mkj.h38
-rw-r--r--src/adplug/core/msc.cc171
-rw-r--r--src/adplug/core/msc.h113
-rw-r--r--src/adplug/core/mtk.cc137
-rw-r--r--src/adplug/core/mtk.h40
-rw-r--r--src/adplug/core/opl.h18
-rw-r--r--src/adplug/core/player.cc49
-rw-r--r--src/adplug/core/player.h84
-rw-r--r--src/adplug/core/players.cc18
-rw-r--r--src/adplug/core/players.h14
-rw-r--r--src/adplug/core/protrack.cc892
-rw-r--r--src/adplug/core/psi.cc86
-rw-r--r--src/adplug/core/psi.h12
-rw-r--r--src/adplug/core/rad.cc164
-rw-r--r--src/adplug/core/rad.h28
-rw-r--r--src/adplug/core/rat.cc196
-rw-r--r--src/adplug/core/rat.h20
-rw-r--r--src/adplug/core/raw.cc91
-rw-r--r--src/adplug/core/raw.h42
-rw-r--r--src/adplug/core/rix.cc718
-rw-r--r--src/adplug/core/rix.h10
-rw-r--r--src/adplug/core/rol.cc51
-rw-r--r--src/adplug/core/rol.h15
-rw-r--r--src/adplug/core/s3m.cc789
-rw-r--r--src/adplug/core/s3m.h136
-rw-r--r--src/adplug/core/sa2.cc291
-rw-r--r--src/adplug/core/sa2.h46
-rw-r--r--src/adplug/core/silentopl.h10
-rw-r--r--src/adplug/core/sng.cc86
-rw-r--r--src/adplug/core/sng.h54
-rw-r--r--src/adplug/core/temuopl.cc70
-rw-r--r--src/adplug/core/temuopl.h8
-rw-r--r--src/adplug/core/u6m.cc968
-rw-r--r--src/adplug/core/u6m.h241
-rw-r--r--src/adplug/core/xad.cc93
-rw-r--r--src/adplug/core/xad.h56
-rw-r--r--src/adplug/core/xsm.cc113
-rw-r--r--src/adplug/core/xsm.h16
-rw-r--r--src/alarm/alarm.cc49
-rw-r--r--src/alarm/interface.cc131
-rw-r--r--src/alarm/interface.h4
-rw-r--r--src/albumart-qt/albumart.cc101
-rw-r--r--src/albumart/albumart.cc18
-rw-r--r--src/amidi-plug/Makefile9
-rw-r--r--src/amidi-plug/amidi-plug.cc2
-rw-r--r--src/amidi-plug/backend-fluidsynth/b-fluidsynth.cc10
-rw-r--r--src/amidi-plug/i_backend.h6
-rw-r--r--src/amidi-plug/i_configure-fluidsynth.cc36
-rw-r--r--src/amidi-plug/i_configure-fluidsynth.h2
-rw-r--r--src/amidi-plug/i_configure.cc8
-rw-r--r--src/amidi-plug/i_fileinfo.cc56
-rw-r--r--src/aosd/aosd.cc1
-rw-r--r--src/aosd/aosd.h1
-rw-r--r--src/aosd/aosd_cfg.cc3
-rw-r--r--src/aosd/aosd_osd.cc14
-rw-r--r--src/aosd/aosd_style.cc8
-rw-r--r--src/aosd/aosd_trigger.cc19
-rw-r--r--src/aosd/aosd_ui.cc172
-rw-r--r--src/blur_scope/blur_scope.cc20
-rw-r--r--src/cairo-spectrum/cairo-spectrum.cc5
-rw-r--r--src/cd-menu-items/Makefile3
-rw-r--r--src/cd-menu-items/cd-menu-items.cc4
-rw-r--r--src/cdaudio-ng/cdaudio-ng.cc9
-rw-r--r--src/coreaudio/coreaudio.cc10
-rw-r--r--src/crossfade/crossfade.cc70
-rw-r--r--src/cue/cue.cc132
-rw-r--r--src/delete-files/delete-files.cc11
-rw-r--r--src/ffaudio/ffaudio-core.cc2
-rw-r--r--src/filewriter/filewriter.cc454
-rw-r--r--src/filewriter/filewriter.h17
-rw-r--r--src/filewriter/flac.cc3
-rw-r--r--src/filewriter/mp3.cc617
-rw-r--r--src/filewriter/plugins.h39
-rw-r--r--src/filewriter/vorbis.cc48
-rw-r--r--src/filewriter/wav.cc3
-rw-r--r--src/flacng/metadata.cc57
-rw-r--r--src/gio/gio.cc76
-rw-r--r--src/gl-spectrum-qt/gl-spectrum.cc3
-rw-r--r--src/gl-spectrum/gl-spectrum.cc57
-rw-r--r--src/gtkui/columns.cc9
-rw-r--r--src/gtkui/layout.cc39
-rw-r--r--src/gtkui/menus.cc26
-rw-r--r--src/gtkui/playlist_util.cc24
-rw-r--r--src/gtkui/ui_gtk.cc176
-rw-r--r--src/gtkui/ui_infoarea.cc111
-rw-r--r--src/gtkui/ui_playlist_notebook.cc23
-rw-r--r--src/gtkui/ui_playlist_widget.cc53
-rw-r--r--src/gtkui/ui_statusbar.cc2
-rw-r--r--src/hotkey/grab.cc2
-rw-r--r--src/hotkey/gui.cc52
-rw-r--r--src/hotkey/plugin.cc63
-rw-r--r--src/hotkey/plugin.h6
-rw-r--r--src/jack-ng/jack-ng.cc11
-rw-r--r--src/ladspa/plugin.cc21
-rw-r--r--src/lirc/lirc.cc3
-rw-r--r--src/lyricwiki-qt/lyricwiki.cc230
-rw-r--r--src/lyricwiki/lyricwiki.cc285
-rw-r--r--src/m3u/m3u.cc35
-rw-r--r--src/mixer/mixer.cc25
-rw-r--r--src/modplug/modplugbmp.cc8
-rw-r--r--src/modplug/modplugbmp.h4
-rw-r--r--src/modplug/plugin_main.cc5
-rw-r--r--src/mpg123/mpg123.cc350
-rw-r--r--src/mpris2/plugin.cc53
-rw-r--r--src/neon/cert_verification.cc70
-rw-r--r--src/neon/neon.cc63
-rw-r--r--src/notify/event.cc36
-rw-r--r--src/notify/event.h4
-rw-r--r--src/notify/notify.cc4
-rw-r--r--src/notify/osd.cc14
-rw-r--r--src/notify/osd.h2
-rw-r--r--src/oss4/oss.cc20
-rw-r--r--src/oss4/oss.h1
-rw-r--r--src/oss4/plugin.cc3
-rw-r--r--src/oss4/utils.cc3
-rw-r--r--src/playlist-manager-qt/Makefile13
-rw-r--r--src/playlist-manager-qt/playlist-manager-qt.cc336
-rw-r--r--src/playlist-manager/playlist-manager.cc10
-rw-r--r--src/psf/eng_protos.h3
-rw-r--r--src/qtui/Makefile3
-rw-r--r--src/qtui/dialog_windows.cc19
-rw-r--r--src/qtui/dialog_windows.h3
-rw-r--r--src/qtui/filter_input.cc2
-rw-r--r--src/qtui/filter_input.h4
-rw-r--r--src/qtui/info_bar.cc245
-rw-r--r--src/qtui/info_bar.h74
-rw-r--r--src/qtui/main_window.cc125
-rw-r--r--src/qtui/main_window.h16
-rw-r--r--src/qtui/main_window_actions.cc39
-rw-r--r--src/qtui/playlist.cc98
-rw-r--r--src/qtui/playlist.h14
-rw-r--r--src/qtui/playlist_model.cc22
-rw-r--r--src/qtui/playlist_tabs.cc199
-rw-r--r--src/qtui/playlist_tabs.h38
-rw-r--r--src/qtui/qtui.cc25
-rw-r--r--src/qtui/settings.cc74
-rw-r--r--src/qtui/settings.h28
-rw-r--r--src/qtui/status_bar.cc2
-rw-r--r--src/qtui/status_bar.h2
-rw-r--r--src/qtui/time_slider.cc5
-rw-r--r--src/qtui/time_slider.h7
-rw-r--r--src/qtui/tool_bar.cc9
-rw-r--r--src/qtui/tool_bar.h11
-rw-r--r--src/scrobbler2/config_window.cc66
-rw-r--r--src/scrobbler2/scrobbler.cc30
-rw-r--r--src/scrobbler2/scrobbler_communication.cc116
-rw-r--r--src/scrobbler2/scrobbler_xml_parsing.cc48
-rw-r--r--src/search-tool-qt/Makefile13
-rw-r--r--src/search-tool-qt/search-tool-qt.cc769
-rw-r--r--src/search-tool/search-tool.cc149
-rw-r--r--src/sid/xs_config.cc2
-rw-r--r--src/sid/xs_config.h2
-rw-r--r--src/skins-data/Makefile124
-rw-r--r--src/skins-data/Skins/Classic/balance.png (renamed from src/skins/Skins/Classic/balance.png)bin814 -> 814 bytes
-rw-r--r--src/skins-data/Skins/Classic/cbuttons.png (renamed from src/skins/Skins/Classic/cbuttons.png)bin3987 -> 3987 bytes
-rw-r--r--src/skins-data/Skins/Classic/eq_ex.png (renamed from src/skins/Skins/Classic/eq_ex.png)bin1566 -> 1566 bytes
-rw-r--r--src/skins-data/Skins/Classic/eqmain.png (renamed from src/skins/Skins/Classic/eqmain.png)bin3675 -> 3675 bytes
-rw-r--r--src/skins-data/Skins/Classic/main.png (renamed from src/skins/Skins/Classic/main.png)bin5001 -> 5001 bytes
-rw-r--r--src/skins-data/Skins/Classic/monoster.png (renamed from src/skins/Skins/Classic/monoster.png)bin312 -> 312 bytes
-rw-r--r--src/skins-data/Skins/Classic/nums_ex.png (renamed from src/skins/Skins/Classic/nums_ex.png)bin288 -> 288 bytes
-rw-r--r--src/skins-data/Skins/Classic/playpaus.png (renamed from src/skins/Skins/Classic/playpaus.png)bin217 -> 217 bytes
-rw-r--r--src/skins-data/Skins/Classic/pledit.png (renamed from src/skins/Skins/Classic/pledit.png)bin19807 -> 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)bin417 -> 417 bytes
-rw-r--r--src/skins-data/Skins/Classic/shufrep.png (renamed from src/skins/Skins/Classic/shufrep.png)bin1032 -> 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)bin610 -> 610 bytes
-rw-r--r--src/skins-data/Skins/Classic/titlebar.png (renamed from src/skins/Skins/Classic/titlebar.png)bin7750 -> 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)bin780 -> 780 bytes
-rw-r--r--src/skins-data/Skins/Classic1.3/balance.png (renamed from src/skins/Skins/Classic1.3/balance.png)bin1457 -> 1457 bytes
-rw-r--r--src/skins-data/Skins/Classic1.3/cbuttons.png (renamed from src/skins/Skins/Classic1.3/cbuttons.png)bin4291 -> 4291 bytes
-rw-r--r--src/skins-data/Skins/Classic1.3/eq_ex.png (renamed from src/skins/Skins/Classic1.3/eq_ex.png)bin1566 -> 1566 bytes
-rw-r--r--src/skins-data/Skins/Classic1.3/eqmain.png (renamed from src/skins/Skins/Classic1.3/eqmain.png)bin3675 -> 3675 bytes
-rw-r--r--src/skins-data/Skins/Classic1.3/main.png (renamed from src/skins/Skins/Classic1.3/main.png)bin1889 -> 1889 bytes
-rw-r--r--src/skins-data/Skins/Classic1.3/monoster.png (renamed from src/skins/Skins/Classic1.3/monoster.png)bin312 -> 312 bytes
-rw-r--r--src/skins-data/Skins/Classic1.3/nums_ex.png (renamed from src/skins/Skins/Classic1.3/nums_ex.png)bin288 -> 288 bytes
-rw-r--r--src/skins-data/Skins/Classic1.3/playpaus.png (renamed from src/skins/Skins/Classic1.3/playpaus.png)bin217 -> 217 bytes
-rw-r--r--src/skins-data/Skins/Classic1.3/pledit.png (renamed from src/skins/Skins/Classic1.3/pledit.png)bin19807 -> 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)bin541 -> 541 bytes
-rw-r--r--src/skins-data/Skins/Classic1.3/shufrep.png (renamed from src/skins/Skins/Classic1.3/shufrep.png)bin2365 -> 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)bin610 -> 610 bytes
-rw-r--r--src/skins-data/Skins/Classic1.3/titlebar.png (renamed from src/skins/Skins/Classic1.3/titlebar.png)bin6233 -> 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)bin1627 -> 1627 bytes
-rw-r--r--src/skins-data/Skins/Default/balance.png (renamed from src/skins/Skins/Default/balance.png)bin1457 -> 1457 bytes
-rw-r--r--src/skins-data/Skins/Default/cbuttons.png (renamed from src/skins/Skins/Default/cbuttons.png)bin2937 -> 2937 bytes
-rw-r--r--src/skins-data/Skins/Default/eq_ex.png (renamed from src/skins/Skins/Default/eq_ex.png)bin2198 -> 2198 bytes
-rw-r--r--src/skins-data/Skins/Default/eqmain.png (renamed from src/skins/Skins/Default/eqmain.png)bin5982 -> 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)bin163 -> 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)bin190 -> 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)bin165 -> 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)bin170 -> 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)bin188 -> 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)bin237 -> 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)bin237 -> 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)bin611 -> 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)bin147 -> 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)bin214 -> 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)bin180 -> 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)bin300 -> 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)bin150 -> 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)bin226 -> 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)bin249 -> 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)bin278 -> 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)bin333 -> 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)bin330 -> 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)bin246 -> 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)bin273 -> 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)bin131 -> 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)bin131 -> 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)bin152 -> 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)bin141 -> 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)bin137 -> 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)bin142 -> 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)bin142 -> 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)bin182 -> 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)bin428 -> 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)bin129 -> 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)bin165 -> 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)bin222 -> 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)bin661 -> 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)bin260 -> 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)bin196 -> 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)bin332 -> 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)bin131 -> 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)bin156 -> 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)bin212 -> 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)bin139 -> 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)bin429 -> 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)bin246 -> 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)bin420 -> 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)bin190 -> 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)bin168 -> 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)bin188 -> 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)bin172 -> 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)bin155 -> 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)bin162 -> 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)bin145 -> 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)bin231 -> 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)bin182 -> 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)bin214 -> 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)bin200 -> 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)bin450 -> 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)bin228 -> 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)bin469 -> 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)bin242 -> 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)bin462 -> 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)bin246 -> 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)bin474 -> 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)bin236 -> 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)bin342 -> 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)bin325 -> 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)bin151 -> 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)bin151 -> 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)bin136 -> 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)bin136 -> 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)bin226 -> 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)bin334 -> 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)bin231 -> 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)bin232 -> 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)bin353 -> 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)bin224 -> 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)bin188 -> 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)bin188 -> 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)bin188 -> 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)bin188 -> 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)bin188 -> 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)bin187 -> 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)bin199 -> 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)bin189 -> 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)bin190 -> 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)bin155 -> 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)bin235 -> 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)bin222 -> 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)bin240 -> 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)bin216 -> 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)bin236 -> 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)bin221 -> 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)bin230 -> 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)bin240 -> 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)bin134 -> 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)bin1419 -> 1419 bytes
-rw-r--r--src/skins-data/Skins/Default/monoster.png (renamed from src/skins/Skins/Default/monoster.png)bin1372 -> 1372 bytes
-rw-r--r--src/skins-data/Skins/Default/nums_ex.png (renamed from src/skins/Skins/Default/nums_ex.png)bin762 -> 762 bytes
-rw-r--r--src/skins-data/Skins/Default/playpaus.png (renamed from src/skins/Skins/Default/playpaus.png)bin444 -> 444 bytes
-rw-r--r--src/skins-data/Skins/Default/pledit.png (renamed from src/skins/Skins/Default/pledit.png)bin15074 -> 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)bin346 -> 346 bytes
-rw-r--r--src/skins-data/Skins/Default/shufrep.png (renamed from src/skins/Skins/Default/shufrep.png)bin3044 -> 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)bin898 -> 898 bytes
-rw-r--r--src/skins-data/Skins/Default/titlebar.png (renamed from src/skins/Skins/Default/titlebar.png)bin4702 -> 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)bin624 -> 624 bytes
-rw-r--r--src/skins-data/Skins/Ivory/balance.png (renamed from src/skins/Skins/Ivory/balance.png)bin745 -> 745 bytes
-rw-r--r--src/skins-data/Skins/Ivory/cbuttons.png (renamed from src/skins/Skins/Ivory/cbuttons.png)bin2352 -> 2352 bytes
-rw-r--r--src/skins-data/Skins/Ivory/eq_ex.png (renamed from src/skins/Skins/Ivory/eq_ex.png)bin1089 -> 1089 bytes
-rw-r--r--src/skins-data/Skins/Ivory/eqmain.png (renamed from src/skins/Skins/Ivory/eqmain.png)bin2783 -> 2783 bytes
-rw-r--r--src/skins-data/Skins/Ivory/main.png (renamed from src/skins/Skins/Ivory/main.png)bin431 -> 431 bytes
-rw-r--r--src/skins-data/Skins/Ivory/monoster.png (renamed from src/skins/Skins/Ivory/monoster.png)bin262 -> 262 bytes
-rw-r--r--src/skins-data/Skins/Ivory/nums_ex.png (renamed from src/skins/Skins/Ivory/nums_ex.png)bin243 -> 243 bytes
-rw-r--r--src/skins-data/Skins/Ivory/playpaus.png (renamed from src/skins/Skins/Ivory/playpaus.png)bin163 -> 163 bytes
-rw-r--r--src/skins-data/Skins/Ivory/pledit.png (renamed from src/skins/Skins/Ivory/pledit.png)bin2090 -> 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)bin320 -> 320 bytes
-rw-r--r--src/skins-data/Skins/Ivory/shufrep.png (renamed from src/skins/Skins/Ivory/shufrep.png)bin890 -> 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)bin574 -> 574 bytes
-rw-r--r--src/skins-data/Skins/Ivory/titlebar.png (renamed from src/skins/Skins/Ivory/titlebar.png)bin7704 -> 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)bin717 -> 717 bytes
-rw-r--r--src/skins-data/Skins/Osmosis/balance.png (renamed from src/skins/Skins/Osmosis/balance.png)bin785 -> 785 bytes
-rw-r--r--src/skins-data/Skins/Osmosis/cbuttons.png (renamed from src/skins/Skins/Osmosis/cbuttons.png)bin2415 -> 2415 bytes
-rw-r--r--src/skins-data/Skins/Osmosis/eq_ex.png (renamed from src/skins/Skins/Osmosis/eq_ex.png)bin1140 -> 1140 bytes
-rw-r--r--src/skins-data/Skins/Osmosis/eqmain.png (renamed from src/skins/Skins/Osmosis/eqmain.png)bin2850 -> 2850 bytes
-rw-r--r--src/skins-data/Skins/Osmosis/main.png (renamed from src/skins/Skins/Osmosis/main.png)bin487 -> 487 bytes
-rw-r--r--src/skins-data/Skins/Osmosis/monoster.png (renamed from src/skins/Skins/Osmosis/monoster.png)bin312 -> 312 bytes
-rw-r--r--src/skins-data/Skins/Osmosis/nums_ex.png (renamed from src/skins/Skins/Osmosis/nums_ex.png)bin288 -> 288 bytes
-rw-r--r--src/skins-data/Skins/Osmosis/playpaus.png (renamed from src/skins/Skins/Osmosis/playpaus.png)bin217 -> 217 bytes
-rw-r--r--src/skins-data/Skins/Osmosis/pledit.png (renamed from src/skins/Skins/Osmosis/pledit.png)bin2148 -> 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)bin362 -> 362 bytes
-rw-r--r--src/skins-data/Skins/Osmosis/shufrep.png (renamed from src/skins/Skins/Osmosis/shufrep.png)bin930 -> 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)bin610 -> 610 bytes
-rw-r--r--src/skins-data/Skins/Osmosis/titlebar.png (renamed from src/skins/Skins/Osmosis/titlebar.png)bin7625 -> 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)bin758 -> 758 bytes
-rw-r--r--src/skins-data/Skins/Refugee/cbuttons.png (renamed from src/skins/Skins/Refugee/cbuttons.png)bin5032 -> 5032 bytes
-rw-r--r--src/skins-data/Skins/Refugee/eq_ex.png (renamed from src/skins/Skins/Refugee/eq_ex.png)bin7580 -> 7580 bytes
-rw-r--r--src/skins-data/Skins/Refugee/eqmain.png (renamed from src/skins/Skins/Refugee/eqmain.png)bin15218 -> 15218 bytes
-rw-r--r--src/skins-data/Skins/Refugee/main.png (renamed from src/skins/Skins/Refugee/main.png)bin11342 -> 11342 bytes
-rw-r--r--src/skins-data/Skins/Refugee/monoster.png (renamed from src/skins/Skins/Refugee/monoster.png)bin1372 -> 1372 bytes
-rw-r--r--src/skins-data/Skins/Refugee/numbers.png (renamed from src/skins/Skins/Refugee/numbers.png)bin1150 -> 1150 bytes
-rw-r--r--src/skins-data/Skins/Refugee/nums_ex.png (renamed from src/skins/Skins/Refugee/nums_ex.png)bin1258 -> 1258 bytes
-rw-r--r--src/skins-data/Skins/Refugee/playpaus.png (renamed from src/skins/Skins/Refugee/playpaus.png)bin682 -> 682 bytes
-rw-r--r--src/skins-data/Skins/Refugee/pledit.png (renamed from src/skins/Skins/Refugee/pledit.png)bin24756 -> 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)bin2061 -> 2061 bytes
-rw-r--r--src/skins-data/Skins/Refugee/shufrep.png (renamed from src/skins/Skins/Refugee/shufrep.png)bin6413 -> 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)bin1262 -> 1262 bytes
-rw-r--r--src/skins-data/Skins/Refugee/titlebar.png (renamed from src/skins/Skins/Refugee/titlebar.png)bin10919 -> 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)bin3327 -> 3327 bytes
-rw-r--r--src/skins-data/Skins/TinyPlayer/balance.png (renamed from src/skins/Skins/TinyPlayer/balance.png)bin814 -> 814 bytes
-rw-r--r--src/skins-data/Skins/TinyPlayer/cbuttons.png (renamed from src/skins/Skins/TinyPlayer/cbuttons.png)bin3987 -> 3987 bytes
-rw-r--r--src/skins-data/Skins/TinyPlayer/eq_ex.png (renamed from src/skins/Skins/TinyPlayer/eq_ex.png)bin1566 -> 1566 bytes
-rw-r--r--src/skins-data/Skins/TinyPlayer/eqmain.png (renamed from src/skins/Skins/TinyPlayer/eqmain.png)bin3675 -> 3675 bytes
-rw-r--r--src/skins-data/Skins/TinyPlayer/main.png (renamed from src/skins/Skins/TinyPlayer/main.png)bin4601 -> 4601 bytes
-rw-r--r--src/skins-data/Skins/TinyPlayer/monoster.png (renamed from src/skins/Skins/TinyPlayer/monoster.png)bin312 -> 312 bytes
-rw-r--r--src/skins-data/Skins/TinyPlayer/nums_ex.png (renamed from src/skins/Skins/TinyPlayer/nums_ex.png)bin288 -> 288 bytes
-rw-r--r--src/skins-data/Skins/TinyPlayer/playpaus.png (renamed from src/skins/Skins/TinyPlayer/playpaus.png)bin217 -> 217 bytes
-rw-r--r--src/skins-data/Skins/TinyPlayer/pledit.png (renamed from src/skins/Skins/TinyPlayer/pledit.png)bin19807 -> 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)bin417 -> 417 bytes
-rw-r--r--src/skins-data/Skins/TinyPlayer/shufrep.png (renamed from src/skins/Skins/TinyPlayer/shufrep.png)bin1032 -> 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)bin610 -> 610 bytes
-rw-r--r--src/skins-data/Skins/TinyPlayer/titlebar.png (renamed from src/skins/Skins/TinyPlayer/titlebar.png)bin7750 -> 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)bin780 -> 780 bytes
-rw-r--r--src/skins-qt/Makefile44
-rw-r--r--src/skins-qt/actions-mainwin.h31
-rw-r--r--src/skins-qt/actions-playlist.h83
-rw-r--r--src/skins-qt/actions.cc295
-rw-r--r--src/skins-qt/button.cc132
-rw-r--r--src/skins-qt/button.h78
-rw-r--r--src/skins-qt/dnd.h56
-rw-r--r--src/skins-qt/dock.cc (renamed from src/skins/ui_dock.cc)246
-rw-r--r--src/skins-qt/drag-handle.cc66
-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.cc135
-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.cc124
-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.cc285
-rw-r--r--src/skins-qt/equalizer.h (renamed from src/skins/ui_equalizer.h)28
-rw-r--r--src/skins-qt/hslider.cc129
-rw-r--r--src/skins-qt/hslider.h70
-rw-r--r--src/skins-qt/main.cc1185
-rw-r--r--src/skins-qt/main.h (renamed from src/skins/ui_main.h)68
-rw-r--r--src/skins-qt/menurow.cc122
-rw-r--r--src/skins-qt/menurow.h62
-rw-r--r--src/skins-qt/menus.cc295
-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.h45
-rw-r--r--src/skins-qt/number.cc60
-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.cc123
-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.cc773
-rw-r--r--src/skins-qt/playlist-widget.h98
-rw-r--r--src/skins-qt/playlist.cc538
-rw-r--r--src/skins-qt/playlist.h (renamed from src/skins/ui_playlist.h)17
-rw-r--r--src/skins-qt/playstatus.cc63
-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.cc208
-rw-r--r--src/skins-qt/plugin-window.h (renamed from src/skins/preset-browser.h)20
-rw-r--r--src/skins-qt/plugin.cc200
-rw-r--r--src/skins-qt/plugin.h30
-rw-r--r--src/skins-qt/skin-ini.cc278
-rw-r--r--src/skins-qt/skin.cc531
-rw-r--r--src/skins-qt/skin.h198
-rw-r--r--src/skins-qt/skins_cfg.cc348
-rw-r--r--src/skins-qt/skins_cfg.h57
-rw-r--r--src/skins-qt/skinselector.cc129
-rw-r--r--src/skins-qt/skinselector.h37
-rw-r--r--src/skins-qt/svis.cc208
-rw-r--r--src/skins-qt/textbox.cc294
-rw-r--r--src/skins-qt/textbox.h82
-rw-r--r--src/skins-qt/util.cc356
-rw-r--r--src/skins-qt/util.h52
-rw-r--r--src/skins-qt/view.cc291
-rw-r--r--src/skins-qt/view.h56
-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.cc318
-rw-r--r--src/skins-qt/vis.h90
-rw-r--r--src/skins-qt/widget.cc (renamed from src/skins/ui_skinned_window.h)41
-rw-r--r--src/skins-qt/widget.h83
-rw-r--r--src/skins-qt/window.cc161
-rw-r--r--src/skins-qt/window.h76
-rw-r--r--src/skins/Makefile175
-rw-r--r--src/skins/actions-mainwin.h12
-rw-r--r--src/skins/actions-playlist.h99
-rw-r--r--src/skins/actions.cc282
-rw-r--r--src/skins/button.cc132
-rw-r--r--src/skins/button.h78
-rw-r--r--src/skins/dock.cc356
-rw-r--r--src/skins/drag-handle.cc86
-rw-r--r--src/skins/drag-handle.h20
-rw-r--r--src/skins/draw-compat.h50
-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.cc127
-rw-r--r--src/skins/eq-slider.h55
-rw-r--r--src/skins/equalizer.cc289
-rw-r--r--src/skins/equalizer.h38
-rw-r--r--src/skins/hslider.cc129
-rw-r--r--src/skins/hslider.h70
-rw-r--r--src/skins/main.cc1227
-rw-r--r--src/skins/main.h73
-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.cc103
-rw-r--r--src/skins/menus.h6
-rw-r--r--src/skins/monostereo.cc61
-rw-r--r--src/skins/monostereo.h (renamed from src/skins/ui_skinned_monostereo.h)15
-rw-r--r--src/skins/number.cc60
-rw-r--r--src/skins/number.h40
-rw-r--r--src/skins/playlist-slider.cc123
-rw-r--r--src/skins/playlist-slider.h55
-rw-r--r--src/skins/playlist-widget.cc813
-rw-r--r--src/skins/playlist-widget.h97
-rw-r--r--src/skins/playlist.cc551
-rw-r--r--src/skins/playlist.h39
-rw-r--r--src/skins/playstatus.cc (renamed from src/skins/ui_skinned_horizontal_slider.h)48
-rw-r--r--src/skins/playstatus.h51
-rw-r--r--src/skins/plugin-window.cc19
-rw-r--r--src/skins/plugin-window.h8
-rw-r--r--src/skins/plugin.cc121
-rw-r--r--src/skins/plugin.h16
-rw-r--r--src/skins/preset-browser.cc158
-rw-r--r--src/skins/preset-list.cc462
-rw-r--r--src/skins/search-select.cc204
-rw-r--r--src/skins/skin-ini.cc278
-rw-r--r--src/skins/skin.cc457
-rw-r--r--src/skins/skin.h (renamed from src/skins/ui_skin.h)47
-rw-r--r--src/skins/skins_cfg.cc192
-rw-r--r--src/skins/skins_cfg.h15
-rw-r--r--src/skins/skinselector.cc237
-rw-r--r--src/skins/skinselector.h (renamed from src/skins/ui_skinselector.h)0
-rw-r--r--src/skins/surface.cc6
-rw-r--r--src/skins/svis.cc (renamed from src/skins/ui_svis.cc)88
-rw-r--r--src/skins/textbox.cc311
-rw-r--r--src/skins/textbox.h80
-rw-r--r--src/skins/ui_equalizer.cc498
-rw-r--r--src/skins/ui_main.cc1352
-rw-r--r--src/skins/ui_playlist.cc1163
-rw-r--r--src/skins/ui_skin.cc809
-rw-r--r--src/skins/ui_skin_load_ini.cc315
-rw-r--r--src/skins/ui_skinned_button.cc264
-rw-r--r--src/skins/ui_skinned_button.h46
-rw-r--r--src/skins/ui_skinned_equalizer_slider.cc191
-rw-r--r--src/skins/ui_skinned_horizontal_slider.cc241
-rw-r--r--src/skins/ui_skinned_number.cc93
-rw-r--r--src/skins/ui_skinned_playlist.cc945
-rw-r--r--src/skins/ui_skinned_playlist.h45
-rw-r--r--src/skins/ui_skinned_playlist_slider.cc144
-rw-r--r--src/skins/ui_skinned_playstatus.cc82
-rw-r--r--src/skins/ui_skinned_textbox.cc412
-rw-r--r--src/skins/ui_skinned_window.cc246
-rw-r--r--src/skins/ui_skinselector.cc398
-rw-r--r--src/skins/util.cc354
-rw-r--r--src/skins/util.h25
-rw-r--r--src/skins/view.cc164
-rw-r--r--src/skins/view.h20
-rw-r--r--src/skins/vis-callbacks.cc222
-rw-r--r--src/skins/vis-callbacks.h26
-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.cc125
-rw-r--r--src/skins/widget.h93
-rw-r--r--src/skins/window.cc184
-rw-r--r--src/skins/window.h81
-rw-r--r--src/sndfile/plugin.cc45
-rw-r--r--src/sndio-ng/sndio.cc41
-rw-r--r--src/song-info-qt/song-info.cc9
-rw-r--r--src/song_change/Makefile3
-rw-r--r--src/song_change/formatter.cc99
-rw-r--r--src/song_change/formatter.h22
-rw-r--r--src/song_change/song_change.cc322
-rw-r--r--src/statusicon-qt/Makefile13
-rw-r--r--src/statusicon-qt/statusicon.cc192
-rw-r--r--src/statusicon/statusicon.cc6
-rw-r--r--src/vorbis/vcedit.cc2
-rw-r--r--src/vorbis/vcedit.h4
-rw-r--r--src/vorbis/vcupdate.cc3
-rw-r--r--src/vorbis/vorbis.cc179
-rw-r--r--src/vorbis/vorbis.h3
-rw-r--r--src/vtx/Makefile8
-rw-r--r--src/vtx/ayemu_vtxfile.h2
-rw-r--r--src/vtx/info.cc4
-rw-r--r--src/vtx/lh5dec.cc6
-rw-r--r--src/vtx/vtx.cc2
-rw-r--r--src/vtx/vtxfile.cc2
-rw-r--r--src/wavpack/wavpack.cc2
-rw-r--r--src/xsf/desmume/NDSSystem.h2
-rw-r--r--src/xsf/plugin.cc2
-rw-r--r--src/xspf/xspf.cc2
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 &param)
+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
index 1493934..1493934 100644
--- a/src/skins/Skins/Classic/balance.png
+++ b/src/skins-data/Skins/Classic/balance.png
Binary files differ
diff --git a/src/skins/Skins/Classic/cbuttons.png b/src/skins-data/Skins/Classic/cbuttons.png
index 40dea8c..40dea8c 100644
--- a/src/skins/Skins/Classic/cbuttons.png
+++ b/src/skins-data/Skins/Classic/cbuttons.png
Binary files differ
diff --git a/src/skins/Skins/Classic/eq_ex.png b/src/skins-data/Skins/Classic/eq_ex.png
index a693a84..a693a84 100644
--- a/src/skins/Skins/Classic/eq_ex.png
+++ b/src/skins-data/Skins/Classic/eq_ex.png
Binary files differ
diff --git a/src/skins/Skins/Classic/eqmain.png b/src/skins-data/Skins/Classic/eqmain.png
index fab90e8..fab90e8 100644
--- a/src/skins/Skins/Classic/eqmain.png
+++ b/src/skins-data/Skins/Classic/eqmain.png
Binary files differ
diff --git a/src/skins/Skins/Classic/main.png b/src/skins-data/Skins/Classic/main.png
index 25184ae..25184ae 100644
--- a/src/skins/Skins/Classic/main.png
+++ b/src/skins-data/Skins/Classic/main.png
Binary files differ
diff --git a/src/skins/Skins/Classic/monoster.png b/src/skins-data/Skins/Classic/monoster.png
index 84f0bc5..84f0bc5 100644
--- a/src/skins/Skins/Classic/monoster.png
+++ b/src/skins-data/Skins/Classic/monoster.png
Binary files differ
diff --git a/src/skins/Skins/Classic/nums_ex.png b/src/skins-data/Skins/Classic/nums_ex.png
index fd7f178..fd7f178 100644
--- a/src/skins/Skins/Classic/nums_ex.png
+++ b/src/skins-data/Skins/Classic/nums_ex.png
Binary files differ
diff --git a/src/skins/Skins/Classic/playpaus.png b/src/skins-data/Skins/Classic/playpaus.png
index bc0c0a6..bc0c0a6 100644
--- a/src/skins/Skins/Classic/playpaus.png
+++ b/src/skins-data/Skins/Classic/playpaus.png
Binary files differ
diff --git a/src/skins/Skins/Classic/pledit.png b/src/skins-data/Skins/Classic/pledit.png
index 6351be8..6351be8 100644
--- a/src/skins/Skins/Classic/pledit.png
+++ b/src/skins-data/Skins/Classic/pledit.png
Binary files differ
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
index cdb3677..cdb3677 100644
--- a/src/skins/Skins/Classic/posbar.png
+++ b/src/skins-data/Skins/Classic/posbar.png
Binary files differ
diff --git a/src/skins/Skins/Classic/shufrep.png b/src/skins-data/Skins/Classic/shufrep.png
index d98aa90..d98aa90 100644
--- a/src/skins/Skins/Classic/shufrep.png
+++ b/src/skins-data/Skins/Classic/shufrep.png
Binary files differ
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
index 24ddfcf..24ddfcf 100644
--- a/src/skins/Skins/Classic/text.png
+++ b/src/skins-data/Skins/Classic/text.png
Binary files differ
diff --git a/src/skins/Skins/Classic/titlebar.png b/src/skins-data/Skins/Classic/titlebar.png
index acd0503..acd0503 100644
--- a/src/skins/Skins/Classic/titlebar.png
+++ b/src/skins-data/Skins/Classic/titlebar.png
Binary files differ
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
index 9bf72ea..9bf72ea 100644
--- a/src/skins/Skins/Classic/volume.png
+++ b/src/skins-data/Skins/Classic/volume.png
Binary files differ
diff --git a/src/skins/Skins/Classic1.3/balance.png b/src/skins-data/Skins/Classic1.3/balance.png
index 35274ac..35274ac 100644
--- a/src/skins/Skins/Classic1.3/balance.png
+++ b/src/skins-data/Skins/Classic1.3/balance.png
Binary files differ
diff --git a/src/skins/Skins/Classic1.3/cbuttons.png b/src/skins-data/Skins/Classic1.3/cbuttons.png
index 1bf7a6e..1bf7a6e 100644
--- a/src/skins/Skins/Classic1.3/cbuttons.png
+++ b/src/skins-data/Skins/Classic1.3/cbuttons.png
Binary files differ
diff --git a/src/skins/Skins/Classic1.3/eq_ex.png b/src/skins-data/Skins/Classic1.3/eq_ex.png
index a693a84..a693a84 100644
--- a/src/skins/Skins/Classic1.3/eq_ex.png
+++ b/src/skins-data/Skins/Classic1.3/eq_ex.png
Binary files differ
diff --git a/src/skins/Skins/Classic1.3/eqmain.png b/src/skins-data/Skins/Classic1.3/eqmain.png
index fab90e8..fab90e8 100644
--- a/src/skins/Skins/Classic1.3/eqmain.png
+++ b/src/skins-data/Skins/Classic1.3/eqmain.png
Binary files differ
diff --git a/src/skins/Skins/Classic1.3/main.png b/src/skins-data/Skins/Classic1.3/main.png
index 94f7529..94f7529 100644
--- a/src/skins/Skins/Classic1.3/main.png
+++ b/src/skins-data/Skins/Classic1.3/main.png
Binary files differ
diff --git a/src/skins/Skins/Classic1.3/monoster.png b/src/skins-data/Skins/Classic1.3/monoster.png
index 84f0bc5..84f0bc5 100644
--- a/src/skins/Skins/Classic1.3/monoster.png
+++ b/src/skins-data/Skins/Classic1.3/monoster.png
Binary files differ
diff --git a/src/skins/Skins/Classic1.3/nums_ex.png b/src/skins-data/Skins/Classic1.3/nums_ex.png
index fd7f178..fd7f178 100644
--- a/src/skins/Skins/Classic1.3/nums_ex.png
+++ b/src/skins-data/Skins/Classic1.3/nums_ex.png
Binary files differ
diff --git a/src/skins/Skins/Classic1.3/playpaus.png b/src/skins-data/Skins/Classic1.3/playpaus.png
index bc0c0a6..bc0c0a6 100644
--- a/src/skins/Skins/Classic1.3/playpaus.png
+++ b/src/skins-data/Skins/Classic1.3/playpaus.png
Binary files differ
diff --git a/src/skins/Skins/Classic1.3/pledit.png b/src/skins-data/Skins/Classic1.3/pledit.png
index 6351be8..6351be8 100644
--- a/src/skins/Skins/Classic1.3/pledit.png
+++ b/src/skins-data/Skins/Classic1.3/pledit.png
Binary files differ
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
index d6a6e48..d6a6e48 100644
--- a/src/skins/Skins/Classic1.3/posbar.png
+++ b/src/skins-data/Skins/Classic1.3/posbar.png
Binary files differ
diff --git a/src/skins/Skins/Classic1.3/shufrep.png b/src/skins-data/Skins/Classic1.3/shufrep.png
index c10ef47..c10ef47 100644
--- a/src/skins/Skins/Classic1.3/shufrep.png
+++ b/src/skins-data/Skins/Classic1.3/shufrep.png
Binary files differ
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
index 24ddfcf..24ddfcf 100644
--- a/src/skins/Skins/Classic1.3/text.png
+++ b/src/skins-data/Skins/Classic1.3/text.png
Binary files differ
diff --git a/src/skins/Skins/Classic1.3/titlebar.png b/src/skins-data/Skins/Classic1.3/titlebar.png
index bcc1b4a..bcc1b4a 100644
--- a/src/skins/Skins/Classic1.3/titlebar.png
+++ b/src/skins-data/Skins/Classic1.3/titlebar.png
Binary files differ
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
index df98142..df98142 100644
--- a/src/skins/Skins/Classic1.3/volume.png
+++ b/src/skins-data/Skins/Classic1.3/volume.png
Binary files differ
diff --git a/src/skins/Skins/Default/balance.png b/src/skins-data/Skins/Default/balance.png
index 35274ac..35274ac 100644
--- a/src/skins/Skins/Default/balance.png
+++ b/src/skins-data/Skins/Default/balance.png
Binary files differ
diff --git a/src/skins/Skins/Default/cbuttons.png b/src/skins-data/Skins/Default/cbuttons.png
index bfd1939..bfd1939 100644
--- a/src/skins/Skins/Default/cbuttons.png
+++ b/src/skins-data/Skins/Default/cbuttons.png
Binary files differ
diff --git a/src/skins/Skins/Default/eq_ex.png b/src/skins-data/Skins/Default/eq_ex.png
index b34aaa3..b34aaa3 100644
--- a/src/skins/Skins/Default/eq_ex.png
+++ b/src/skins-data/Skins/Default/eq_ex.png
Binary files differ
diff --git a/src/skins/Skins/Default/eqmain.png b/src/skins-data/Skins/Default/eqmain.png
index 0a2d91a..0a2d91a 100644
--- a/src/skins/Skins/Default/eqmain.png
+++ b/src/skins-data/Skins/Default/eqmain.png
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index 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
Binary files differ
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
index fa1bec3..fa1bec3 100644
--- a/src/skins/Skins/Default/main.png
+++ b/src/skins-data/Skins/Default/main.png
Binary files differ
diff --git a/src/skins/Skins/Default/monoster.png b/src/skins-data/Skins/Default/monoster.png
index dab972a..dab972a 100644
--- a/src/skins/Skins/Default/monoster.png
+++ b/src/skins-data/Skins/Default/monoster.png
Binary files differ
diff --git a/src/skins/Skins/Default/nums_ex.png b/src/skins-data/Skins/Default/nums_ex.png
index 53adeeb..53adeeb 100644
--- a/src/skins/Skins/Default/nums_ex.png
+++ b/src/skins-data/Skins/Default/nums_ex.png
Binary files differ
diff --git a/src/skins/Skins/Default/playpaus.png b/src/skins-data/Skins/Default/playpaus.png
index 3e1c564..3e1c564 100644
--- a/src/skins/Skins/Default/playpaus.png
+++ b/src/skins-data/Skins/Default/playpaus.png
Binary files differ
diff --git a/src/skins/Skins/Default/pledit.png b/src/skins-data/Skins/Default/pledit.png
index 4d4a51a..4d4a51a 100644
--- a/src/skins/Skins/Default/pledit.png
+++ b/src/skins-data/Skins/Default/pledit.png
Binary files differ
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
index f229e05..f229e05 100644
--- a/src/skins/Skins/Default/posbar.png
+++ b/src/skins-data/Skins/Default/posbar.png
Binary files differ
diff --git a/src/skins/Skins/Default/shufrep.png b/src/skins-data/Skins/Default/shufrep.png
index d7f6d56..d7f6d56 100644
--- a/src/skins/Skins/Default/shufrep.png
+++ b/src/skins-data/Skins/Default/shufrep.png
Binary files differ
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
index eee0c83..eee0c83 100644
--- a/src/skins/Skins/Default/text.png
+++ b/src/skins-data/Skins/Default/text.png
Binary files differ
diff --git a/src/skins/Skins/Default/titlebar.png b/src/skins-data/Skins/Default/titlebar.png
index f1dde49..f1dde49 100644
--- a/src/skins/Skins/Default/titlebar.png
+++ b/src/skins-data/Skins/Default/titlebar.png
Binary files differ
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
index 37611da..37611da 100644
--- a/src/skins/Skins/Default/volume.png
+++ b/src/skins-data/Skins/Default/volume.png
Binary files differ
diff --git a/src/skins/Skins/Ivory/balance.png b/src/skins-data/Skins/Ivory/balance.png
index fc3c7ac..fc3c7ac 100644
--- a/src/skins/Skins/Ivory/balance.png
+++ b/src/skins-data/Skins/Ivory/balance.png
Binary files differ
diff --git a/src/skins/Skins/Ivory/cbuttons.png b/src/skins-data/Skins/Ivory/cbuttons.png
index f5f68e7..f5f68e7 100644
--- a/src/skins/Skins/Ivory/cbuttons.png
+++ b/src/skins-data/Skins/Ivory/cbuttons.png
Binary files differ
diff --git a/src/skins/Skins/Ivory/eq_ex.png b/src/skins-data/Skins/Ivory/eq_ex.png
index e231f71..e231f71 100644
--- a/src/skins/Skins/Ivory/eq_ex.png
+++ b/src/skins-data/Skins/Ivory/eq_ex.png
Binary files differ
diff --git a/src/skins/Skins/Ivory/eqmain.png b/src/skins-data/Skins/Ivory/eqmain.png
index 2b0b834..2b0b834 100644
--- a/src/skins/Skins/Ivory/eqmain.png
+++ b/src/skins-data/Skins/Ivory/eqmain.png
Binary files differ
diff --git a/src/skins/Skins/Ivory/main.png b/src/skins-data/Skins/Ivory/main.png
index d020ea8..d020ea8 100644
--- a/src/skins/Skins/Ivory/main.png
+++ b/src/skins-data/Skins/Ivory/main.png
Binary files differ
diff --git a/src/skins/Skins/Ivory/monoster.png b/src/skins-data/Skins/Ivory/monoster.png
index 2746a2f..2746a2f 100644
--- a/src/skins/Skins/Ivory/monoster.png
+++ b/src/skins-data/Skins/Ivory/monoster.png
Binary files differ
diff --git a/src/skins/Skins/Ivory/nums_ex.png b/src/skins-data/Skins/Ivory/nums_ex.png
index 5a5260f..5a5260f 100644
--- a/src/skins/Skins/Ivory/nums_ex.png
+++ b/src/skins-data/Skins/Ivory/nums_ex.png
Binary files differ
diff --git a/src/skins/Skins/Ivory/playpaus.png b/src/skins-data/Skins/Ivory/playpaus.png
index ef6e329..ef6e329 100644
--- a/src/skins/Skins/Ivory/playpaus.png
+++ b/src/skins-data/Skins/Ivory/playpaus.png
Binary files differ
diff --git a/src/skins/Skins/Ivory/pledit.png b/src/skins-data/Skins/Ivory/pledit.png
index a209b14..a209b14 100644
--- a/src/skins/Skins/Ivory/pledit.png
+++ b/src/skins-data/Skins/Ivory/pledit.png
Binary files differ
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
index ba32396..ba32396 100644
--- a/src/skins/Skins/Ivory/posbar.png
+++ b/src/skins-data/Skins/Ivory/posbar.png
Binary files differ
diff --git a/src/skins/Skins/Ivory/shufrep.png b/src/skins-data/Skins/Ivory/shufrep.png
index 85b10cb..85b10cb 100644
--- a/src/skins/Skins/Ivory/shufrep.png
+++ b/src/skins-data/Skins/Ivory/shufrep.png
Binary files differ
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
index d32bb1a..d32bb1a 100644
--- a/src/skins/Skins/Ivory/text.png
+++ b/src/skins-data/Skins/Ivory/text.png
Binary files differ
diff --git a/src/skins/Skins/Ivory/titlebar.png b/src/skins-data/Skins/Ivory/titlebar.png
index 827e6a2..827e6a2 100644
--- a/src/skins/Skins/Ivory/titlebar.png
+++ b/src/skins-data/Skins/Ivory/titlebar.png
Binary files differ
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
index 63335f6..63335f6 100644
--- a/src/skins/Skins/Ivory/volume.png
+++ b/src/skins-data/Skins/Ivory/volume.png
Binary files differ
diff --git a/src/skins/Skins/Osmosis/balance.png b/src/skins-data/Skins/Osmosis/balance.png
index 6f8176f..6f8176f 100644
--- a/src/skins/Skins/Osmosis/balance.png
+++ b/src/skins-data/Skins/Osmosis/balance.png
Binary files differ
diff --git a/src/skins/Skins/Osmosis/cbuttons.png b/src/skins-data/Skins/Osmosis/cbuttons.png
index db3002f..db3002f 100644
--- a/src/skins/Skins/Osmosis/cbuttons.png
+++ b/src/skins-data/Skins/Osmosis/cbuttons.png
Binary files differ
diff --git a/src/skins/Skins/Osmosis/eq_ex.png b/src/skins-data/Skins/Osmosis/eq_ex.png
index abbfee3..abbfee3 100644
--- a/src/skins/Skins/Osmosis/eq_ex.png
+++ b/src/skins-data/Skins/Osmosis/eq_ex.png
Binary files differ
diff --git a/src/skins/Skins/Osmosis/eqmain.png b/src/skins-data/Skins/Osmosis/eqmain.png
index 9035e87..9035e87 100644
--- a/src/skins/Skins/Osmosis/eqmain.png
+++ b/src/skins-data/Skins/Osmosis/eqmain.png
Binary files differ
diff --git a/src/skins/Skins/Osmosis/main.png b/src/skins-data/Skins/Osmosis/main.png
index 68933fe..68933fe 100644
--- a/src/skins/Skins/Osmosis/main.png
+++ b/src/skins-data/Skins/Osmosis/main.png
Binary files differ
diff --git a/src/skins/Skins/Osmosis/monoster.png b/src/skins-data/Skins/Osmosis/monoster.png
index 84f0bc5..84f0bc5 100644
--- a/src/skins/Skins/Osmosis/monoster.png
+++ b/src/skins-data/Skins/Osmosis/monoster.png
Binary files differ
diff --git a/src/skins/Skins/Osmosis/nums_ex.png b/src/skins-data/Skins/Osmosis/nums_ex.png
index fd7f178..fd7f178 100644
--- a/src/skins/Skins/Osmosis/nums_ex.png
+++ b/src/skins-data/Skins/Osmosis/nums_ex.png
Binary files differ
diff --git a/src/skins/Skins/Osmosis/playpaus.png b/src/skins-data/Skins/Osmosis/playpaus.png
index bc0c0a6..bc0c0a6 100644
--- a/src/skins/Skins/Osmosis/playpaus.png
+++ b/src/skins-data/Skins/Osmosis/playpaus.png
Binary files differ
diff --git a/src/skins/Skins/Osmosis/pledit.png b/src/skins-data/Skins/Osmosis/pledit.png
index fc56bd7..fc56bd7 100644
--- a/src/skins/Skins/Osmosis/pledit.png
+++ b/src/skins-data/Skins/Osmosis/pledit.png
Binary files differ
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
index 51f42ad..51f42ad 100644
--- a/src/skins/Skins/Osmosis/posbar.png
+++ b/src/skins-data/Skins/Osmosis/posbar.png
Binary files differ
diff --git a/src/skins/Skins/Osmosis/shufrep.png b/src/skins-data/Skins/Osmosis/shufrep.png
index cb33e99..cb33e99 100644
--- a/src/skins/Skins/Osmosis/shufrep.png
+++ b/src/skins-data/Skins/Osmosis/shufrep.png
Binary files differ
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
index 24ddfcf..24ddfcf 100644
--- a/src/skins/Skins/Osmosis/text.png
+++ b/src/skins-data/Skins/Osmosis/text.png
Binary files differ
diff --git a/src/skins/Skins/Osmosis/titlebar.png b/src/skins-data/Skins/Osmosis/titlebar.png
index 55a4297..55a4297 100644
--- a/src/skins/Skins/Osmosis/titlebar.png
+++ b/src/skins-data/Skins/Osmosis/titlebar.png
Binary files differ
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
index bfcc0e7..bfcc0e7 100644
--- a/src/skins/Skins/Osmosis/volume.png
+++ b/src/skins-data/Skins/Osmosis/volume.png
Binary files differ
diff --git a/src/skins/Skins/Refugee/cbuttons.png b/src/skins-data/Skins/Refugee/cbuttons.png
index 2eae7e6..2eae7e6 100644
--- a/src/skins/Skins/Refugee/cbuttons.png
+++ b/src/skins-data/Skins/Refugee/cbuttons.png
Binary files differ
diff --git a/src/skins/Skins/Refugee/eq_ex.png b/src/skins-data/Skins/Refugee/eq_ex.png
index caeed46..caeed46 100644
--- a/src/skins/Skins/Refugee/eq_ex.png
+++ b/src/skins-data/Skins/Refugee/eq_ex.png
Binary files differ
diff --git a/src/skins/Skins/Refugee/eqmain.png b/src/skins-data/Skins/Refugee/eqmain.png
index 51178be..51178be 100644
--- a/src/skins/Skins/Refugee/eqmain.png
+++ b/src/skins-data/Skins/Refugee/eqmain.png
Binary files differ
diff --git a/src/skins/Skins/Refugee/main.png b/src/skins-data/Skins/Refugee/main.png
index 7fec481..7fec481 100644
--- a/src/skins/Skins/Refugee/main.png
+++ b/src/skins-data/Skins/Refugee/main.png
Binary files differ
diff --git a/src/skins/Skins/Refugee/monoster.png b/src/skins-data/Skins/Refugee/monoster.png
index dab972a..dab972a 100644
--- a/src/skins/Skins/Refugee/monoster.png
+++ b/src/skins-data/Skins/Refugee/monoster.png
Binary files differ
diff --git a/src/skins/Skins/Refugee/numbers.png b/src/skins-data/Skins/Refugee/numbers.png
index 1bdb4fa..1bdb4fa 100644
--- a/src/skins/Skins/Refugee/numbers.png
+++ b/src/skins-data/Skins/Refugee/numbers.png
Binary files differ
diff --git a/src/skins/Skins/Refugee/nums_ex.png b/src/skins-data/Skins/Refugee/nums_ex.png
index 76d922f..76d922f 100644
--- a/src/skins/Skins/Refugee/nums_ex.png
+++ b/src/skins-data/Skins/Refugee/nums_ex.png
Binary files differ
diff --git a/src/skins/Skins/Refugee/playpaus.png b/src/skins-data/Skins/Refugee/playpaus.png
index 5d4a837..5d4a837 100644
--- a/src/skins/Skins/Refugee/playpaus.png
+++ b/src/skins-data/Skins/Refugee/playpaus.png
Binary files differ
diff --git a/src/skins/Skins/Refugee/pledit.png b/src/skins-data/Skins/Refugee/pledit.png
index f951c64..f951c64 100644
--- a/src/skins/Skins/Refugee/pledit.png
+++ b/src/skins-data/Skins/Refugee/pledit.png
Binary files differ
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
index 96c2fef..96c2fef 100644
--- a/src/skins/Skins/Refugee/posbar.png
+++ b/src/skins-data/Skins/Refugee/posbar.png
Binary files differ
diff --git a/src/skins/Skins/Refugee/shufrep.png b/src/skins-data/Skins/Refugee/shufrep.png
index 2406a2a..2406a2a 100644
--- a/src/skins/Skins/Refugee/shufrep.png
+++ b/src/skins-data/Skins/Refugee/shufrep.png
Binary files differ
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
index 6bed67b..6bed67b 100644
--- a/src/skins/Skins/Refugee/text.png
+++ b/src/skins-data/Skins/Refugee/text.png
Binary files differ
diff --git a/src/skins/Skins/Refugee/titlebar.png b/src/skins-data/Skins/Refugee/titlebar.png
index 4a052dd..4a052dd 100644
--- a/src/skins/Skins/Refugee/titlebar.png
+++ b/src/skins-data/Skins/Refugee/titlebar.png
Binary files differ
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
index ac3da03..ac3da03 100644
--- a/src/skins/Skins/Refugee/volume.png
+++ b/src/skins-data/Skins/Refugee/volume.png
Binary files differ
diff --git a/src/skins/Skins/TinyPlayer/balance.png b/src/skins-data/Skins/TinyPlayer/balance.png
index 1493934..1493934 100644
--- a/src/skins/Skins/TinyPlayer/balance.png
+++ b/src/skins-data/Skins/TinyPlayer/balance.png
Binary files differ
diff --git a/src/skins/Skins/TinyPlayer/cbuttons.png b/src/skins-data/Skins/TinyPlayer/cbuttons.png
index 40dea8c..40dea8c 100644
--- a/src/skins/Skins/TinyPlayer/cbuttons.png
+++ b/src/skins-data/Skins/TinyPlayer/cbuttons.png
Binary files differ
diff --git a/src/skins/Skins/TinyPlayer/eq_ex.png b/src/skins-data/Skins/TinyPlayer/eq_ex.png
index a693a84..a693a84 100644
--- a/src/skins/Skins/TinyPlayer/eq_ex.png
+++ b/src/skins-data/Skins/TinyPlayer/eq_ex.png
Binary files differ
diff --git a/src/skins/Skins/TinyPlayer/eqmain.png b/src/skins-data/Skins/TinyPlayer/eqmain.png
index fab90e8..fab90e8 100644
--- a/src/skins/Skins/TinyPlayer/eqmain.png
+++ b/src/skins-data/Skins/TinyPlayer/eqmain.png
Binary files differ
diff --git a/src/skins/Skins/TinyPlayer/main.png b/src/skins-data/Skins/TinyPlayer/main.png
index c484d15..c484d15 100644
--- a/src/skins/Skins/TinyPlayer/main.png
+++ b/src/skins-data/Skins/TinyPlayer/main.png
Binary files differ
diff --git a/src/skins/Skins/TinyPlayer/monoster.png b/src/skins-data/Skins/TinyPlayer/monoster.png
index 84f0bc5..84f0bc5 100644
--- a/src/skins/Skins/TinyPlayer/monoster.png
+++ b/src/skins-data/Skins/TinyPlayer/monoster.png
Binary files differ
diff --git a/src/skins/Skins/TinyPlayer/nums_ex.png b/src/skins-data/Skins/TinyPlayer/nums_ex.png
index fd7f178..fd7f178 100644
--- a/src/skins/Skins/TinyPlayer/nums_ex.png
+++ b/src/skins-data/Skins/TinyPlayer/nums_ex.png
Binary files differ
diff --git a/src/skins/Skins/TinyPlayer/playpaus.png b/src/skins-data/Skins/TinyPlayer/playpaus.png
index bc0c0a6..bc0c0a6 100644
--- a/src/skins/Skins/TinyPlayer/playpaus.png
+++ b/src/skins-data/Skins/TinyPlayer/playpaus.png
Binary files differ
diff --git a/src/skins/Skins/TinyPlayer/pledit.png b/src/skins-data/Skins/TinyPlayer/pledit.png
index 6351be8..6351be8 100644
--- a/src/skins/Skins/TinyPlayer/pledit.png
+++ b/src/skins-data/Skins/TinyPlayer/pledit.png
Binary files differ
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
index cdb3677..cdb3677 100644
--- a/src/skins/Skins/TinyPlayer/posbar.png
+++ b/src/skins-data/Skins/TinyPlayer/posbar.png
Binary files differ
diff --git a/src/skins/Skins/TinyPlayer/shufrep.png b/src/skins-data/Skins/TinyPlayer/shufrep.png
index d98aa90..d98aa90 100644
--- a/src/skins/Skins/TinyPlayer/shufrep.png
+++ b/src/skins-data/Skins/TinyPlayer/shufrep.png
Binary files differ
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
index 24ddfcf..24ddfcf 100644
--- a/src/skins/Skins/TinyPlayer/text.png
+++ b/src/skins-data/Skins/TinyPlayer/text.png
Binary files differ
diff --git a/src/skins/Skins/TinyPlayer/titlebar.png b/src/skins-data/Skins/TinyPlayer/titlebar.png
index acd0503..acd0503 100644
--- a/src/skins/Skins/TinyPlayer/titlebar.png
+++ b/src/skins-data/Skins/TinyPlayer/titlebar.png
Binary files differ
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
index 9bf72ea..9bf72ea 100644
--- a/src/skins/Skins/TinyPlayer/volume.png
+++ b/src/skins-data/Skins/TinyPlayer/volume.png
Binary files differ
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));